# PV-Live#

Description of the station network from Lorenz, E. (2021):

“The irradiance measurement network set up in the project PV-Live consists of 40 measurement stations in the control area of the transmission system operator TransnetBW. With their rather even distribution a good representation of the mean irradiance conditions in the grid area is achieved. The distance between neighbouring measurement stations ranges between 15 km and 35 km. Details of the station locations, including coordinates and heights, are given in Table 1. Most stations are installed close to PV power plants. A few of them are located at outposts and buildings of TransnetBW, public utilities and other station partners.

A PV-Live measurement station … consists of a SMP10 thermopile pyranometer (Kipp and Zonen, 2020), which measures GHI, and three Mencke & Tegtmeyer Si sensors (silicon photovoltaic reference cells; Ingenieurbüro Mencke & Tegtmeyer GmbH, 2020), which measure GTI. The three Si sensors are oriented towards east (90°), south (180°) and west (270°) and have tilt angles of 25°. Besides irradiance also temperature is measured by the pyranometer as well as the silicon sensors.

The SMP10 pyranometers are ISO-9060 (International Organization for Standardization, 2018) spectrally flat Class A sensors. They are not equipped with ventilation units, because these would have caused considerable additional costs and an increase in electricity consumption.”

References:

The 40 stations in the network are:

Station name Latitude Longitude Altitude
ID

And a nice map, just to get a sense of the distribution of the stations:

Make this Notebook Trusted to load map: File -> Trust Notebook

## Data availability#

“The PV-Live irradiance and temperature measurements … are made publicly available on the open-access repository Zenodo (European Organization For Nuclear Research and OpenAIRE, 2013) through the DOI: 10.5281/zenodo.4036728 (Dittmann et al., 2021), starting with data of September 2020. The data set is extended by adding data of the previous month on a monthly basis. All measurement values are provided with quality flags as described in Section 6.

Near real-time availability is an important aspect of the PV-Live network. Measurements are taken once per second and stored as oneminute mean values. Near real-time data transfer of these minute values is achieved by using the mobile phone network to establish connections of the measurement stations with Fraunhofer ISE. In addition, the measurements are stored in an internal memory. In case a measurement station is temporarily unavailable, the data is completed automatically, when the connection is re-established.”

Below is an example of how to retrieve time series irradiance data from the PV-Live network.

import urllib.request
import io
import zipfile
import os
import pandas as pd
import warnings

PVLIVE_BASE_URL ='https://zenodo.org/record/7311989/files/'

def get_pvlive(station, start, end):
"""
Retrieve ground measured irradiance data from the PV-Live network.

The PV-Live network consists of 40 solar irradiance measurement stations
across the German state of Baden-Württemberg. All stations measure global
horizontal irradiance and temperature with a pyranometer, and global tilted
irradiance in east, south, and west direction with tilt angles of 25° with
three photovoltaic reference cells in minute resolution [1]_.

Data is available from Zenodo [2]_.

Parameters
----------
station: int
Station number (integer). All stations can be requested by specifying
station='all'.
start: datetime-like
First day of the requested period
end: datetime-like
Last day of the requested period

Returns
-------
data: DataFrame
timeseries data from the PV-LIVE measurement network.

Warns
-----
UserWarning
If one or more requested files are missing a UserWarning is returned.

Notes
-----
Data is returned for the entire months between and including start and end.

Examples
--------
>>> # Retrieve two months irradiance data PV-Live station 1
>>> data, metadata = get_pvlive(station=1,  # doctest: +SKIP
>>>     start=pd.Timestamp(2021,1,1), end=pd.Timestamp(2021,2,28),   # doctest: +SKIP

References
----------
.. [1] High resolution measurement network of global horizontal and tilted solar
irradiance in southern Germany with a new quality control scheme. Elke Lorenz
et al. 2022. Solar Energy.
<https://doi.org/10.1016/j.solener.2021.11.023/>_
.. [2] Zenodo
<https://doi.org/10.5281/zenodo.4036728>_
"""  # noqa: E501

months = pd.date_range(start, end.replace(day=1)+pd.DateOffset(months=1), freq='1M')

dfs_inter_months = []  # Initialize list for holding dataframes
for m in months:
# Generate URL to the monthly ZIP archive
try:
remotezip = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
'outside the available time period')
continue
else:
raise
zip = zipfile.ZipFile(zipinmemory)

dfs_intra_months = []
for filename in zip.namelist():
basename = os.path.basename(filename)  # Extract file basename
# Parse file if extension is file starts wtih 'tng' and ends with '.tsv'
if basename.startswith('tng') & basename.endswith('.tsv'):
# Extract station number from file name
station_number = int(basename[6:8])
if (station=='all') | (station==station_number):
# Read data into pandas dataframe
sep='\t', index_col=[0], parse_dates=[0])

if station == 'all':
# Add station number to column names (MultiIndex)
dfi.columns = [[station_number]*dfi.shape[1], dfi.columns]
dfs_intra_months.append(dfi)
dfs_inter_months.append(pd.concat(dfs_intra_months, axis='columns'))
data = pd.concat(dfs_inter_months, axis='rows')

meta = {}
return data, meta

df, _ = get_pvlive(
station=1,
start=pd.Timestamp(2021,1,1),
end=pd.Timestamp(2021,1,31))

df.loc['2021-01-02 09:00': '2021-01-02 09:05'] # Print six minutes of measurements

Gg_pyr flag_Gg_pyr Gg_si_south flag_Gg_si_south Gg_si_east flag_Gg_si_east Gg_si_west flag_Gg_si_west T_pyr flag_T_pyr flag_shading
datetime
2021-01-02 09:00:00 42.5 0 41.6 0 42.7 0 35.9 0 0.3 0 0
2021-01-02 09:01:00 45.5 0 45.0 0 45.6 0 38.9 0 0.3 0 0
2021-01-02 09:02:00 48.7 0 48.0 0 48.5 0 41.9 0 0.3 0 0
2021-01-02 09:03:00 51.3 0 50.6 0 51.0 0 44.2 0 0.3 0 0
2021-01-02 09:04:00 53.7 0 52.9 0 53.6 0 46.1 0 0.3 0 0
2021-01-02 09:05:00 56.5 0 56.2 0 56.5 0 48.6 0 0.3 0 0

### Visualize measurement data#

_ = df[['Gg_pyr', 'Gg_si_south', 'Gg_si_east', 'Gg_si_west']].plot(
subplots=True, sharex=True, figsize=(6,6))


### Visualize one day of measurement data#

_ = df[['Gg_pyr', 'Gg_si_south', 'Gg_si_east', 'Gg_si_west']].loc['2021-01-16 05':'2021-01-16 18'].plot()


df[['Gg_pyr', 'Gg_si_south', 'Gg_si_east', 'Gg_si_west']].resample('1h').mean().resample('1w').sum().plot.bar()

<AxesSubplot:xlabel='datetime'>