23
23
24
24
URL = 'https://re.jrc.ec.europa.eu/api/'
25
25
26
-
27
- def get_pvgis_hourly (lat , lon , angle = 0 , aspect = 0 ,
28
- outputformat = 'json' , usehorizon = True ,
29
- userhorizon = None , raddatabase = None ,
30
- startyear = None , endyear = None ,
31
- pvcalculation = False , peakpower = None ,
32
- pvtechchoice = 'crystSi' , mountingplace = 'free' , loss = None ,
33
- trackingtype = 0 ,
26
+ # Dictionary mapping PVGIS names to pvlib names
27
+ VARIABLE_MAP = {
28
+ 'G(h)' : 'ghi' ,
29
+ 'Gb(n)' : 'dni' ,
30
+ 'Gd(h)' : 'dhi' ,
31
+ 'G(i)' : 'poa_global' ,
32
+ 'Gb(i)' : 'poa_direct' ,
33
+ 'Gd(i)' : 'poa_diffuse' ,
34
+ 'Gr(i)' : 'poa_ground_diffuse' ,
35
+ 'H_sun' : 'solar_elevation' ,
36
+ 'T2m' : 'temp_air' ,
37
+ 'RH' : 'relative_humidity' ,
38
+ 'SP' : 'pressure' ,
39
+ 'WS10m' : 'wind_speed' ,
40
+ 'WD10m' : 'wind_direction' ,
41
+ }
42
+
43
+
44
+ def get_pvgis_hourly (lat , lon , angle = 0 , aspect = 0 , outputformat = 'json' ,
45
+ usehorizon = True , userhorizon = None , raddatabase = None ,
46
+ startyear = None , endyear = None , pvcalculation = False ,
47
+ peakpower = None , pvtechchoice = 'crystSi' ,
48
+ mountingplace = 'free' , loss = None , trackingtype = 0 ,
34
49
optimal_inclination = False , optimalangles = False ,
35
- components = True , url = URL , timeout = 30 ):
50
+ components = True , url = URL , map_variables = True , timeout = 30 ):
36
51
"""
37
- Get hourly solar radiation data and modeled PV power output from PVGIS
38
- [1]_.
52
+ Get hourly solar irradiation and modeled PV power output from PVGIS [1]_.
39
53
40
54
Parameters
41
55
----------
@@ -49,8 +63,8 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
49
63
Orientation (azimuth angle) of the (fixed) plane. 0=south, 90=west,
50
64
-90: east. Not relevant for tracking systems.
51
65
outputformat: str, default: 'json'
52
- Must be in ``['csv', 'json ']``. See PVGIS hourly data documentation
53
- [2]_ for more info.
66
+ Must be in ``['json', ' csv', 'basic ']``. See PVGIS hourly data
67
+ documentation [2]_ for more info. Note basic does not include a header .
54
68
usehorizon: bool, default: True
55
69
Include effects of horizon
56
70
userhorizon: list of float, default: None
@@ -92,17 +106,45 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
92
106
url: str, default:const:`pvlib.iotools.pvgis.URL`
93
107
Base url of PVGIS API, append ``seriescalc`` to get hourly data
94
108
endpoint
109
+ map_variables: bool, default True
110
+ When true, renames columns of the Dataframe to pvlib variable names
111
+ where applicable. See variable VARIABLE_MAP.
95
112
timeout: int, default: 30
96
113
Time in seconds to wait for server response before timeout
97
114
98
115
Returns
99
116
-------
100
117
data : pandas.DataFrame
101
- Time-series of hourly data
118
+ Time-series of hourly data, see Notes for fields
102
119
inputs : dict
103
- Dictionary of the request input parameters
120
+ Dictionary of the request input parameters, ``None`` for basic
104
121
meta : list or dict
105
- meta data
122
+ meta data, ``None`` for basic
123
+
124
+ Notes
125
+ -----
126
+ data includes the following fields:
127
+
128
+ ======================= ====== ==========================================
129
+ raw, mapped Format Description
130
+ ======================= ====== ==========================================
131
+ **Mapped field names are returned when the map_variables argument is True**
132
+ ---------------------------------------------------------------------------
133
+ P* float PV system power (W)
134
+ G(i)** float Global irradiance on inclined plane (W/m^2)
135
+ Gb(i)** float Beam (direct) irradiance on inclined plane (W/m^2)
136
+ Gd(i)** float Diffuse irradiance on inclined plane (W/m^2)
137
+ Gr(i)** float Reflected irradiance on inclined plane (W/m^2)
138
+ H_sun, solar_elevation float Sun height/elevation (degrees)
139
+ T2m, temp_air float Air temperature at 2 (degrees Celsius)
140
+ WS10m, wind_speed float Wind speed at 10 m (m/s)
141
+ Int int Solar radiation reconstructed (1/0)
142
+ ======================= ====== ==========================================
143
+
144
+ *P (PV system power) is only returned when pvcalculation=True.
145
+
146
+ **Gb(i), Gd(i), and Gr(i) are returned when components=True, whereas
147
+ otherwise the sum of the three components, G(i), is returned.
106
148
107
149
Raises
108
150
------
@@ -113,7 +155,7 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
113
155
114
156
See also
115
157
--------
116
- pvlib.iotools.read_pvgis_hourly
158
+ pvlib.iotools.read_pvgis_hourly, pvlib.iotools.get_pvgis_tmy
117
159
118
160
References
119
161
----------
@@ -173,10 +215,10 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
173
215
data = None , None , None , None
174
216
if outputformat == 'json' :
175
217
src = res .json ()
176
- return _parse_pvgis_hourly_json (src )
218
+ return _parse_pvgis_hourly_json (src , map_variables = map_variables )
177
219
elif outputformat == 'csv' :
178
220
with io .StringIO (res .content .decode ('utf-8' )) as src :
179
- return _parse_pvgis_hourly_csv (src )
221
+ return _parse_pvgis_hourly_csv (src , map_variables = map_variables )
180
222
elif outputformat == 'basic' :
181
223
with io .BytesIO (res .content ) as src :
182
224
return _parse_pvgis_hourly_basic (src )
@@ -187,13 +229,15 @@ def get_pvgis_hourly(lat, lon, angle=0, aspect=0,
187
229
return data
188
230
189
231
190
- def _parse_pvgis_hourly_json (src ):
232
+ def _parse_pvgis_hourly_json (src , map_variables = True ):
191
233
inputs = src ['inputs' ]
192
234
meta = src ['meta' ]
193
235
data = pd .DataFrame (src ['outputs' ]['hourly' ])
194
236
data .index = pd .to_datetime (data ['time' ], format = '%Y%m%d:%H%M' , utc = True )
195
237
data = data .drop ('time' , axis = 1 )
196
238
data = data .astype (dtype = {'Int' : 'int' }) # The 'Int' column to be integer
239
+ if map_variables :
240
+ data .rename (columns = VARIABLE_MAP , inplace = True )
197
241
return data , inputs , meta
198
242
199
243
@@ -203,7 +247,7 @@ def _parse_pvgis_hourly_basic(src):
203
247
return data , None , None
204
248
205
249
206
- def _parse_pvgis_hourly_csv (src ):
250
+ def _parse_pvgis_hourly_csv (src , map_variables = True ):
207
251
# The first 4 rows are latitude, longitude, elevation, radiation database
208
252
inputs = {}
209
253
# 'Latitude (decimal degrees): 45.000\r\n'
@@ -215,7 +259,6 @@ def _parse_pvgis_hourly_csv(src):
215
259
# 'Radiation database: \tPVGIS-SARAH\r\n'
216
260
inputs ['radiation_database' ] = str (src .readline ().split (':' )[1 ]
217
261
.replace ('\t ' , '' ).replace ('\n ' , '' ))
218
-
219
262
# Parse through the remaining metadata section (the number of lines for
220
263
# this section depends on the requested parameters)
221
264
while True :
@@ -229,9 +272,8 @@ def _parse_pvgis_hourly_csv(src):
229
272
inputs [line .split (':' )[0 ]] = str (line .split (':' )[1 ]
230
273
.replace ('\n ' , '' )
231
274
.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
275
+ # Save the entries from the data section to a list, until an empty line is
276
+ # reached an empty line. The length of the section depends on the request
235
277
data_lines = []
236
278
while True :
237
279
line = src .readline ()
@@ -240,22 +282,22 @@ def _parse_pvgis_hourly_csv(src):
240
282
else :
241
283
data_lines .append (line .replace ('\n ' , '' ).replace ('\r ' , '' )
242
284
.split (',' ))
243
-
244
285
data = pd .DataFrame (data_lines , columns = names )
245
286
data .index = pd .to_datetime (data ['time' ], format = '%Y%m%d:%H%M' , utc = True )
246
287
data = data .drop ('time' , axis = 1 )
288
+ if map_variables :
289
+ data .rename (columns = VARIABLE_MAP , inplace = True )
247
290
# All columns should have the dtype=float, except 'Int' which should be
248
291
# integer. It is necessary to convert to float, before converting to int
249
292
data = data .astype (float ).astype (dtype = {'Int' : 'int' })
250
-
251
293
# Generate metadata dictionary containing description of parameters
252
294
meta = {}
253
295
for line in src .readlines ():
254
296
if ':' in line :
255
297
meta [line .split (':' )[0 ]] = line .split (':' )[1 ].strip ()
256
-
257
298
return data , inputs , meta
258
299
300
+
259
301
def get_pvgis_tmy (lat , lon , outputformat = 'json' , usehorizon = True ,
260
302
userhorizon = None , startyear = None , endyear = None , url = URL ,
261
303
timeout = 30 ):
0 commit comments