Tools - Module Standoff for IEC TS 63126#

Calculation of module standoff distance according to IEC TS 63126#

Requirements:

  • Local weather data file or site longitude and latittude

Objectives:

  1. Import weather data.

  2. Calculate installation standoff - Level 1 and Level 2.

  3. Calculate \(X_{eff}\) from provided module temperature data.

  4. Calculate \(T_{98}\) for a given azimuth, tilt, and \(X_{eff}\).

  5. Plot \(X_{min}\) for all azimuth and tilt for a given \(T_{98}\).

  6. Plot \(X_{min}\) for Level 1, Level 2, or a \(T_{98}\) for a given region.

Background:

This notebook calculates the a minimum effective standoff distance (\(X_{eff}\)) necessary for roof-mounted PV modules to ensure that the \(98^{th}\) percentile operating temperature, \(T_{98}\), remains under 70°C for compliance to IEC 61730 and IEC 61215. For higher \(T_{98}\) values above 70°C or 80°C testing must be done to the specifications for Level 1 and Level 2 of IEC TS 63126. This method is outlined in the appendix of IEC TS 63126 and is based on the model from *[King 2004] and data from **[Fuentes, 1987] to model the approximate exponential decay in temperature, \(T(X)\), with increasing standoff distance, \(X\), as,

\[ X = -X_0 \ln\left(1-\frac{T_0-T}{\Delta T}\right), Equation 1 \]

where \(T_0\) is the temperature for \(X=0\) (insulated-back) and \(\Delta T\) is the temperature difference between an insulated-back (\(X=0\)) and open-rack mounting configuration (\(X=\infty)\).

We used pvlib and data from the National Solar Radiation Database (NSRDB) to calculate the module temperatures for the insulated-back and open-rack mounting configurations and apply our model to obtain the minimum standoff distance for roof-mounted PV systems to achieve a temperature lower than a specified \(T_{98}\). The following figure showcases this calulation for the entire world for an \(X_{eff}\) that results in \(T_{98}\)=70°C. Values of \(X_{eff}\) higher than this will require Level 1 or Level 2 certification.

\(*\) D. L. King, W. E. Boyson, and J. A. Kratochvil, “Photovoltaic array performance model,” SAND2004-3535, Sandia National Laboratories, Albuquerque, NM, 2004. ‘
\(**\) M. K. Fuentes, “A simplified thermal model for Flat-Plate photovoltaic arrays,” United States, 1987-05-01 1987. https://www.osti.gov/biblio/6802914

alt text

# if running on google colab, uncomment the next line and execute this cell to install the dependencies 
# and prevent "ModuleNotFoundError" in later cells:
!pip install pvdeg==0.4.2
Requirement already satisfied: pvdeg==0.4.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (0.4.2)
Requirement already satisfied: aiohttp==3.9.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.9.5)
Requirement already satisfied: numpy==1.26.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (1.26.4)
Requirement already satisfied: pvlib==0.10.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.10.3)
Requirement already satisfied: scipy<1.14.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (1.13.1)
Requirement already satisfied: NREL-rex in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.2.90)
Requirement already satisfied: cartopy in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.23.0)
Requirement already satisfied: dask[dataframe] in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (2024.9.0)
Requirement already satisfied: dask-jobqueue in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.9.0)
Requirement already satisfied: bokeh in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.5.2)
Requirement already satisfied: h5netcdf in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: h5py in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.11.0)
Requirement already satisfied: jupyterlab in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (4.2.5)
Requirement already satisfied: matplotlib in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.9.2)
Requirement already satisfied: netCDF4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (1.7.1.post2)
Requirement already satisfied: notebook in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (7.2.2)
Requirement already satisfied: numba in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.60.0)
Requirement already satisfied: openpyxl in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.1.5)
Requirement already satisfied: pandas in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (2.2.2)
Requirement already satisfied: photovoltaic in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.1.9)
Requirement already satisfied: python-dateutil in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (2.9.0.post0)
Requirement already satisfied: pytz in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (2024.2)
Requirement already satisfied: seaborn in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (0.13.2)
Requirement already satisfied: tables in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.10.1)
Requirement already satisfied: tqdm in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (4.66.5)
Requirement already satisfied: xarray in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (2024.9.0)
Requirement already satisfied: pre-commit in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (3.8.0)
Requirement already satisfied: sympy in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvdeg==0.4.2) (1.13.2)
Requirement already satisfied: aiosignal>=1.1.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from aiohttp==3.9.5->pvdeg==0.4.2) (1.3.1)
Requirement already satisfied: attrs>=17.3.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from aiohttp==3.9.5->pvdeg==0.4.2) (24.2.0)
Requirement already satisfied: frozenlist>=1.1.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from aiohttp==3.9.5->pvdeg==0.4.2) (1.4.1)
Requirement already satisfied: multidict<7.0,>=4.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from aiohttp==3.9.5->pvdeg==0.4.2) (6.1.0)
Requirement already satisfied: yarl<2.0,>=1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from aiohttp==3.9.5->pvdeg==0.4.2) (1.11.1)
Requirement already satisfied: requests in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pvlib==0.10.3->pvdeg==0.4.2) (2.32.3)
Requirement already satisfied: tzdata>=2022.7 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pandas->pvdeg==0.4.2) (2024.1)
Requirement already satisfied: six>=1.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from python-dateutil->pvdeg==0.4.2) (1.16.0)
Requirement already satisfied: Jinja2>=2.9 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (3.1.4)
Requirement already satisfied: contourpy>=1.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: packaging>=16.8 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (24.1)
Requirement already satisfied: pillow>=7.1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (10.4.0)
Requirement already satisfied: PyYAML>=3.10 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (6.0.2)
Requirement already satisfied: tornado>=6.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (6.4.1)
Requirement already satisfied: xyzservices>=2021.09.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bokeh->pvdeg==0.4.2) (2024.9.0)
Requirement already satisfied: shapely>=1.7 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from cartopy->pvdeg==0.4.2) (2.0.6)
Requirement already satisfied: pyshp>=2.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from cartopy->pvdeg==0.4.2) (2.3.1)
Requirement already satisfied: pyproj>=3.3.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from cartopy->pvdeg==0.4.2) (3.6.1)
Requirement already satisfied: cycler>=0.10 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from matplotlib->pvdeg==0.4.2) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from matplotlib->pvdeg==0.4.2) (4.53.1)
Requirement already satisfied: kiwisolver>=1.3.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from matplotlib->pvdeg==0.4.2) (1.4.7)
Requirement already satisfied: pyparsing>=2.3.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from matplotlib->pvdeg==0.4.2) (3.1.4)
Requirement already satisfied: distributed>=2022.02.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask-jobqueue->pvdeg==0.4.2) (2024.9.0)
Requirement already satisfied: click>=8.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (8.1.7)
Requirement already satisfied: cloudpickle>=3.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (3.0.0)
Requirement already satisfied: fsspec>=2021.09.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (2024.9.0)
Requirement already satisfied: partd>=1.4.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (1.4.2)
Requirement already satisfied: toolz>=0.10.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (0.12.1)
Requirement already satisfied: importlib-metadata>=4.13.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (8.5.0)
Requirement already satisfied: dask-expr<1.2,>=1.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask[dataframe]->pvdeg==0.4.2) (1.1.14)
Requirement already satisfied: async-lru>=1.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (2.0.4)
Requirement already satisfied: httpx>=0.25.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (0.27.2)
Requirement already satisfied: ipykernel>=6.5.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (6.29.5)
Requirement already satisfied: jupyter-core in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (5.7.2)
Requirement already satisfied: jupyter-lsp>=2.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (2.2.5)
Requirement already satisfied: jupyter-server<3,>=2.4.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (2.14.2)
Requirement already satisfied: jupyterlab-server<3,>=2.27.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (2.27.3)
Requirement already satisfied: notebook-shim>=0.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (0.2.4)
Requirement already satisfied: setuptools>=40.1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (65.5.0)
Requirement already satisfied: traitlets in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab->pvdeg==0.4.2) (5.14.3)
Requirement already satisfied: cftime in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from netCDF4->pvdeg==0.4.2) (1.6.4)
Requirement already satisfied: certifi in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from netCDF4->pvdeg==0.4.2) (2024.8.30)
Requirement already satisfied: h5pyd>=0.18.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from NREL-rex->pvdeg==0.4.2) (0.18.0)
Requirement already satisfied: psutil>=5.6 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from NREL-rex->pvdeg==0.4.2) (6.0.0)
Requirement already satisfied: scikit-learn>=1.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from NREL-rex->pvdeg==0.4.2) (1.5.2)
Requirement already satisfied: toml>=0.10.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from NREL-rex->pvdeg==0.4.2) (0.10.2)
Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from numba->pvdeg==0.4.2) (0.43.0)
Requirement already satisfied: et-xmlfile in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from openpyxl->pvdeg==0.4.2) (1.1.0)
Requirement already satisfied: cfgv>=2.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pre-commit->pvdeg==0.4.2) (3.4.0)
Requirement already satisfied: identify>=1.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pre-commit->pvdeg==0.4.2) (2.6.1)
Requirement already satisfied: nodeenv>=0.11.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pre-commit->pvdeg==0.4.2) (1.9.1)
Requirement already satisfied: virtualenv>=20.10.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from pre-commit->pvdeg==0.4.2) (20.26.4)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from sympy->pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: numexpr>=2.6.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from tables->pvdeg==0.4.2) (2.10.1)
Requirement already satisfied: py-cpuinfo in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from tables->pvdeg==0.4.2) (9.0.0)
Requirement already satisfied: blosc2>=2.3.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from tables->pvdeg==0.4.2) (2.7.1)
Requirement already satisfied: typing-extensions>=4.4.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from tables->pvdeg==0.4.2) (4.12.2)
Requirement already satisfied: ndindex>=1.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from blosc2>=2.3.0->tables->pvdeg==0.4.2) (1.8)
Requirement already satisfied: msgpack in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from blosc2>=2.3.0->tables->pvdeg==0.4.2) (1.1.0)
Requirement already satisfied: pyarrow>=14.0.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from dask-expr<1.2,>=1.1->dask[dataframe]->pvdeg==0.4.2) (17.0.0)
Requirement already satisfied: locket>=1.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from distributed>=2022.02.0->dask-jobqueue->pvdeg==0.4.2) (1.0.0)
Requirement already satisfied: sortedcontainers>=2.0.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from distributed>=2022.02.0->dask-jobqueue->pvdeg==0.4.2) (2.4.0)
Requirement already satisfied: tblib>=1.6.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from distributed>=2022.02.0->dask-jobqueue->pvdeg==0.4.2) (3.0.0)
Requirement already satisfied: urllib3>=1.26.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from distributed>=2022.02.0->dask-jobqueue->pvdeg==0.4.2) (2.2.3)
Requirement already satisfied: zict>=3.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from distributed>=2022.02.0->dask-jobqueue->pvdeg==0.4.2) (3.0.0)
Requirement already satisfied: requests-unixsocket in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from h5pyd>=0.18.0->NREL-rex->pvdeg==0.4.2) (0.3.0)
Requirement already satisfied: pyjwt in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from h5pyd>=0.18.0->NREL-rex->pvdeg==0.4.2) (2.9.0)
Requirement already satisfied: anyio in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from httpx>=0.25.0->jupyterlab->pvdeg==0.4.2) (4.4.0)
Requirement already satisfied: httpcore==1.* in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from httpx>=0.25.0->jupyterlab->pvdeg==0.4.2) (1.0.5)
Requirement already satisfied: idna in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from httpx>=0.25.0->jupyterlab->pvdeg==0.4.2) (3.10)
Requirement already satisfied: sniffio in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from httpx>=0.25.0->jupyterlab->pvdeg==0.4.2) (1.3.1)
Requirement already satisfied: h11<0.15,>=0.13 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from httpcore==1.*->httpx>=0.25.0->jupyterlab->pvdeg==0.4.2) (0.14.0)
Requirement already satisfied: zipp>=3.20 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from importlib-metadata>=4.13.0->dask[dataframe]->pvdeg==0.4.2) (3.20.2)
Requirement already satisfied: comm>=0.1.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.2.2)
Requirement already satisfied: debugpy>=1.6.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (1.8.5)
Requirement already satisfied: ipython>=7.23.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (8.27.0)
Requirement already satisfied: jupyter-client>=6.1.12 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (8.6.2)
Requirement already satisfied: matplotlib-inline>=0.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.1.7)
Requirement already satisfied: nest-asyncio in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (1.6.0)
Requirement already satisfied: pyzmq>=24 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (26.2.0)
Requirement already satisfied: MarkupSafe>=2.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from Jinja2>=2.9->bokeh->pvdeg==0.4.2) (2.1.5)
Requirement already satisfied: platformdirs>=2.5 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-core->jupyterlab->pvdeg==0.4.2) (4.3.3)
Requirement already satisfied: argon2-cffi>=21.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (23.1.0)
Requirement already satisfied: jupyter-events>=0.9.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.10.0)
Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.5.3)
Requirement already satisfied: nbconvert>=6.4.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (7.16.4)
Requirement already satisfied: nbformat>=5.3.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (5.10.4)
Requirement already satisfied: overrides>=5.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (7.7.0)
Requirement already satisfied: prometheus-client>=0.9 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.20.0)
Requirement already satisfied: send2trash>=1.8.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.8.3)
Requirement already satisfied: terminado>=0.8.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.18.1)
Requirement already satisfied: websocket-client>=1.7 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.8.0)
Requirement already satisfied: babel>=2.10 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (2.16.0)
Requirement already satisfied: json5>=0.9.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (0.9.25)
Requirement already satisfied: jsonschema>=4.18.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (4.23.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from requests->pvlib==0.10.3->pvdeg==0.4.2) (3.3.2)
Requirement already satisfied: joblib>=1.2.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from scikit-learn>=1.3->NREL-rex->pvdeg==0.4.2) (1.4.2)
Requirement already satisfied: threadpoolctl>=3.1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from scikit-learn>=1.3->NREL-rex->pvdeg==0.4.2) (3.5.0)
Requirement already satisfied: distlib<1,>=0.3.7 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from virtualenv>=20.10.0->pre-commit->pvdeg==0.4.2) (0.3.8)
Requirement already satisfied: filelock<4,>=3.12.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from virtualenv>=20.10.0->pre-commit->pvdeg==0.4.2) (3.16.0)
Requirement already satisfied: argon2-cffi-bindings in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (21.2.0)
Requirement already satisfied: decorator in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (5.1.1)
Requirement already satisfied: jedi>=0.16 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.19.1)
Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (3.0.47)
Requirement already satisfied: pygments>=2.4.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (2.18.0)
Requirement already satisfied: stack-data in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.6.3)
Requirement already satisfied: pexpect>4.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (4.9.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (2023.12.1)
Requirement already satisfied: referencing>=0.28.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (0.35.1)
Requirement already satisfied: rpds-py>=0.7.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.27.1->jupyterlab->pvdeg==0.4.2) (0.20.0)
Requirement already satisfied: python-json-logger>=2.0.4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (2.0.7)
Requirement already satisfied: rfc3339-validator in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.1.4)
Requirement already satisfied: rfc3986-validator>=0.1.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.1.1)
Requirement already satisfied: beautifulsoup4 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (4.12.3)
Requirement already satisfied: bleach!=5.0.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (6.1.0)
Requirement already satisfied: defusedxml in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.7.1)
Requirement already satisfied: jupyterlab-pygments in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.3.0)
Requirement already satisfied: mistune<4,>=2.0.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (3.0.2)
Requirement already satisfied: nbclient>=0.5.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.10.0)
Requirement already satisfied: pandocfilters>=1.4.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.5.1)
Requirement already satisfied: tinycss2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: fastjsonschema>=2.15 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from nbformat>=5.3.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (2.20.0)
Requirement already satisfied: ptyprocess in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from terminado>=0.8.3->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.7.0)
Requirement already satisfied: webencodings in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from bleach!=5.0.0->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (0.5.1)
Requirement already satisfied: parso<0.9.0,>=0.8.3 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jedi>=0.16->ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.8.4)
Requirement already satisfied: fqdn in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.5.1)
Requirement already satisfied: isoduration in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (20.11.0)
Requirement already satisfied: jsonpointer>1.13 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (3.0.0)
Requirement already satisfied: uri-template in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: webcolors>=24.6.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (24.8.0)
Requirement already satisfied: wcwidth in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.2.13)
Requirement already satisfied: cffi>=1.0.1 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.17.1)
Requirement already satisfied: soupsieve>1.2 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (2.6)
Requirement already satisfied: executing>=1.2.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from stack-data->ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (2.1.0)
Requirement already satisfied: asttokens>=2.1.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from stack-data->ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (2.4.1)
Requirement already satisfied: pure-eval in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from stack-data->ipython>=7.23.1->ipykernel>=6.5.0->jupyterlab->pvdeg==0.4.2) (0.2.3)
Requirement already satisfied: pycparser in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi>=21.1->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (2.22)
Requirement already satisfied: arrow>=0.15.0 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (1.3.0)
Requirement already satisfied: types-python-dateutil>=2.8.10 in /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=2.4.0->jupyterlab->pvdeg==0.4.2) (2.9.0.20240906)
import os
from pathlib import Path
import pvdeg
import pandas as pd
from pvdeg import DATA_DIR
import dask
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import math
# This information helps with debugging and getting support :)
import sys, platform
print("Working on a ", platform.system(), platform.release())
print("Python version ", sys.version)
print("Pandas version ", pd.__version__)
print("pvdeg version ", pvdeg.__version__)
print("dask version", dask.__version__)
print(DATA_DIR)
Working on a  Linux 6.5.0-1025-azure
Python version  3.11.9 (main, Jul 15 2024, 21:50:21) [GCC 11.4.0]
Pandas version  2.2.2
pvdeg version  0.4.2
dask version 2024.9.0
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pvdeg/data

1. Import Weather Data#

The function has these minimum requirements when using a weather data file:

  • Weather data containing (at least) DNI, DHI, GHI, Temperature, RH, and Wind-Speed data at module level.

  • Site meta-data containing (at least) latitude, longitude, and time zone

Alternatively one may can get meterological data from the NSRDB or PVGIS with just the longitude and latitude. This function for the NSRDB (via NSRDB ‘PSM3’) works primarily for most of North America and South America. PVGIS works for most of the rest of the world (via SARAH ‘PVGIS’). See the tutorial “Weather Database Access.ipynb” tutorial on PVdeg or Jensen et al. https://doi.org/10.1016/j.solener.2023.112092 for satellite coverage information.

# Get data from a supplied data file (Do not use the next box of code if using your own file)
weather_file = os.path.join(DATA_DIR, 'psm3_demo.csv')
WEATHER_df, META = pvdeg.weather.read(weather_file,'csv')
print(META)
{'Source': 'NSRDB', 'Location ID': 145809.0, 'City': '-', 'State': '-', 'Country': '-', 'Clearsky DHI Units': 'w/m2', 'Clearsky DNI Units': 'w/m2', 'Clearsky GHI Units': 'w/m2', 'Dew Point Units': 'c', 'DHI Units': 'w/m2', 'DNI Units': 'w/m2', 'GHI Units': 'w/m2', 'Solar Zenith Angle Units': 'Degree', 'Temperature Units': 'c', 'Pressure Units': 'mbar', 'Relative Humidity Units': '%', 'Precipitable Water Units': 'cm', 'Wind Direction Units': 'Degrees', 'Wind Speed Units': 'm/s', 'Cloud Type -15': 'N/A', 'Cloud Type 0': 'Clear', 'Cloud Type 1': 'Probably Clear', 'Cloud Type 2': 'Fog', 'Cloud Type 3': 'Water', 'Cloud Type 4': 'Super-Cooled Water', 'Cloud Type 5': 'Mixed', 'Cloud Type 6': 'Opaque Ice', 'Cloud Type 7': 'Cirrus', 'Cloud Type 8': 'Overlapping', 'Cloud Type 9': 'Overshooting', 'Cloud Type 10': 'Unknown', 'Cloud Type 11': 'Dust', 'Cloud Type 12': 'Smoke', 'Fill Flag 0': 'N/A', 'Fill Flag 1': 'Missing Image', 'Fill Flag 2': 'Low Irradiance', 'Fill Flag 3': 'Exceeds Clearsky', 'Fill Flag 4': 'Missing CLoud Properties', 'Fill Flag 5': 'Rayleigh Violation', 'Surface Albedo Units': 'N/A', 'Version': '3.0.6', 'latitude': 39.73, 'longitude': -105.18, 'tz': -7.0, 'altitude': 1820.0}
# This routine will get a meteorological dataset from anywhere in the world where it is available 
#weather_id = (24.7136, 46.6753) #Riyadh, Saudi Arabia
#weather_id = (35.6754, 139.65) #Tokyo, Japan
weather_id = (-43.52646, 172.62165) #Christchurch, New Zealand
#weather_id = (64.84031, -147.73836) #Fairbanks, Alaska
#weather_id = (65.14037, -21.91633) #Reykjavik, Iceland
#weather_id = (33.4152, -111.8315) #Mesa, Arizona
WEATHER_df, META = pvdeg.weather.get_anywhere(id=weather_id)
print(META)
{'latitude': -43.52646, 'longitude': 172.62165, 'altitude': 4.0, 'wind_height': 10, 'Source': 'PVGIS'}

2. Calculate Installation Standoff Minimum - Level 1 and Level 2#

According to IEC TS 63126, Level 0, Level 1 and Level 2 certification is limited to T₉₈<70°C, <80°C and <90°C, respectively. Level 0 certification is essentially compliance to IEC 61730 and IEC 61215. The default value of T₉₈<70°C represents the minimium gap to avoid higher temperature certification according to IEC TS 63126. This minimum standoff (\(x_{min}\)) is the distance between the bottom of the module frame and the roof and can be extimated for a given environment as,

\[ X_{min} = -X_0 \ln\left(1-\frac{T_{98,0}-T}{ T_{98,0}- T_{98,inf}}\right), Equation 2 \]

where \(T_{98,0}\) is the \(98^{th}\) percentile temperature for an insulated back module and \(T_{98,inf}\) is the \(98^{th}\) percentile temperature for an open rack mounted module.

Once the meterological data has been obtained, the input parameter possibilities are:

  • T₉₈ : Does not necessarily need to be set at 70°C or 80°C for IEC TS 63216, you might want to use a different number to compensate for a thermal aspect of the particular system you are considering. The default is 70°C.

  • tilt : tilt from horizontal of PV module. The default is 0°.

  • azimuth : azimuth in degrees from North. The default is 180° for south facing.

  • sky_model : pvlib compatible model for generating sky characteristics (Options: ‘isotropic’, ‘klucher’, ‘haydavies’, ‘reindl’, ‘king’, ‘perez’). The default is ‘isotropic’.

  • temp_model : pvlib compatible module temperature model. (Options: ‘sapm’, ‘pvsyst’, ‘faiman’, ‘sandia’). The default is ‘sapm’.

  • conf_0 : Temperature model for hotest mounting configuration. Default is “insulated_back_glass_polymer”.

  • conf_inf : Temperature model for open rack mounting. Default is “open_rack_glass_polymer”.

  • x_0 : thermal decay constant [cm] (see documentation). The default is 6.5 cm.

  • wind_factor : Wind speed power law correction factor to account for different wind speed measurement heights between weather database (e.g. NSRDB) and the tempeature model (e.g. SAPM). The default is 0.33.

The following is the minimum function call. It defaults to horizontal tilt and T₉₈=70°C.

standoff = pvdeg.standards.standoff(weather_df=WEATHER_df, meta=META)
print(pvdeg.standards.interpret_standoff(standoff))
The array tilt angle was not provided, therefore the latitude tilt of -43.5 was used.
The estimated T₉₈ of an insulated-back module is 45.2°C. 
The estimated T₉₈ of an open-rack module is 32.7°C. 
Level 0 certification is valid for a standoff greather than 0.0 cm. 

The following is a full function call for both T₉₈=70°C and 80°C separately even though the second standoff distance can be calculated using only T98_0 and T98_inf. With this function, one may also want to change the tilt, azimuth, or T98.

standoff_1 = pvdeg.standards.standoff(weather_df=WEATHER_df, meta=META,
                                      T98=70, tilt=META['latitude'], azimuth=None,
                                      sky_model='isotropic', temp_model='sapm', conf_0='insulated_back_glass_polymer', conf_inf='open_rack_glass_polymer',
                                      x_0=6.5, wind_factor=0.33)
print('First calculation standoff = ', '%.1f' % standoff_1['x'].iloc[0] , ' cm.')
standoff_2 = pvdeg.standards.standoff(weather_df=WEATHER_df, meta=META,
                                      T98=80, tilt=META['latitude'], azimuth=None,
                                      sky_model='isotropic', temp_model='sapm', conf_0='insulated_back_glass_polymer', conf_inf='open_rack_glass_polymer',
                                      x_0=6.5, wind_factor=0.33)
print('Second calculation standoff = ', '%.1f' % standoff_2['x'].iloc[0] , ' cm.')
print(pvdeg.standards.interpret_standoff(standoff_1=standoff_1, standoff_2=standoff_2))
First calculation standoff =  0.0  cm.
Second calculation standoff =  0.0  cm.
The estimated T₉₈ of an insulated-back module is 45.2°C. 
The estimated T₉₈ of an open-rack module is 32.7°C. 
Level 0 certification is valid for a standoff greather than 0.0 cm. 

3. Calculate \(X_{eff}\) from provided module temperature data.#

To do this calculation, one must use a set of data with:

  • meterological irradiance data sufficient to calculate the POA irradiance (DHI, GHI, and DNI),

  • ambient temperature data,

  • wind speed at module height, (wind_factor=0.33 will be used unless otherwise specified)

  • temperature measurements of the module in the test system. Ideally this would be measured under a worst case scenario that maximizes the module temperature for a given site,

  • geographic meta data including longitude and latitude,

To create a weather file of your own, copy the format of the example file ‘xeff_demo.csv’. This is formatted with the first row containing meta data variable names, the second row containing the corresponding values, the third row containing meteorological data headers, and all the remaining rows containing the meteorological data.

To do this calculation, one should also filter the data to remove times when the sun is not shining or when snow is likely to be on the module. The recommendations and programmed defaults are to use poa_min=100 W/m² and data when the minimum ambient temperature t_amb_min=0.

# Read the weather file
weather_file = os.path.join(DATA_DIR,'xeff_demo.csv')
xeff_weather, xeff_meta = pvdeg.weather.read(weather_file,'csv')
# Pull measured temperature and calculate theoretical insulated back module temperature and open rack module temperature
T_0, T_inf, xeff_poa = pvdeg.standards.eff_gap_parameters(
    weather_df = xeff_weather,
    meta = xeff_meta,
    sky_model = "isotropic",
    temp_model = "sapm",
    conf_0 = "insulated_back_glass_polymer",
    conf_inf = "open_rack_glass_polymer",
    wind_factor = 0.33)
# Now calculate X_eff.
x_eff = pvdeg.standards.eff_gap(T_0, T_inf, xeff_weather['module_temperature'], xeff_weather["temp_air"], xeff_poa['poa_global'], x_0=6.5, poa_min=100, t_amb_min=0)
print ('The effective standoff for this system is', '%.1f' % x_eff , 'cm.')
The effective standoff for this system is 2.0 cm.

4. Calculate \(T_{98}\) for a given azimuth, tilt, and \(X_{eff}\).#

Equation 2 can be reorganized as,

\[ T_{98} = T_{98,0} -( T_{98,0}- T_{98,inf}) \left(1-e^{-\frac{x_{eff}}{x_{0}}}\right), Equation 3 \]

and used to calculate the \(98^{th}\) percential temperature, \(T_{98}\), for a PV system having a given effective standoff height, \(X_{eff}\), for an arbitrarily oriented module. Here, \(T_{98,0}\) is the \(98^{th}\) percentile for an insulated-back module and \(T_{98,inf}\) is the \(98^{th}\) percentile for a rack-mounted module. The input parameter possibilities are the same as shown in Objective #2 above, but the example below uses the default parameters. The actual tilt [degrees], azimuth [degrees] and \(X_{eff}\) [cm] can be modifed as desired.

# This is the minimal function call using the common default settings to estimate T₉₈.
T_98 = pvdeg.standards.T98_estimate(
    weather_df=WEATHER_df,
    meta=META,
    tilt=META['latitude'],
    azimuth=None,
    x_eff=0,)
print ('The 98ᵗʰ percential temperature is estimated to be' , '%.1f' % T_98 , '°C.')
The 98ᵗʰ percential temperature is estimated to be 45.2 °C.

5. Plot \(X_{min}\) for all azimuth and tilt for a given \(T_{98}\).#

The temperature of a system is affected by the orientation. This section will scan all possible tilts and azimuths calculating the minimum standoff distance for a given \(T_{98}\). Similar additional factors as above can also be modified but are not included here for simplicity. The tilt_step and azimuth_step are the number of degrees for each step for the 90° and 180° tilt and azimuth spans, respectively. The default for this calculation is for \(T_{98}\)=70°C, the boundary between Level 0 and Level 1 requirements. The temperature model information given below is unnecessary as these are default values that would get populated automatically. However, they were included here for clarity into a standard practice as per IEC TS 63126.

\[ X_{min} = -X_0 \ln\left(1-\frac{T_{98,0}-T}{ T_{98,0}- T_{98,inf}}\right), Equation 2 \]
#Scans through all the azimuth and tilt running the minimum standoff calculation
#Set up keyword parameters for the calculation

kwarg_x = dict( sky_model="isotropic",
    temp_model="sapm",
    conf_0="insulated_back_glass_polymer",
    conf_inf="open_rack_glass_polymer",
    T98=70,
    x_0=6.5,
    wind_factor=0.33)
#Run the calculation
x_azimuth_step=10
x_tilt_step=10
standoff_series = pvdeg.utilities.tilt_azimuth_scan(weather_df = WEATHER_df, meta=META,
    tilt_step=x_tilt_step, azimuth_step=x_azimuth_step, func = pvdeg.standards.standoff_x, **kwarg_x)
0.3% complete
0.5% complete
0.8% complete
1.1% complete
1.4% complete
1.6% complete
1.9% complete
2.2% complete
2.4% complete
2.7% complete
3.0% complete
3.2% complete
3.5% complete
3.8% complete
4.1% complete
4.3% complete
4.6% complete
4.9% complete
5.1% complete
5.4% complete
5.7% complete
5.9% complete
6.2% complete
6.5% complete
6.8% complete
7.0% complete
7.3% complete
7.6% complete
7.8% complete
8.1% complete
8.4% complete
8.6% complete
8.9% complete
9.2% complete
9.5% complete
9.7% complete
10.0% complete
10.3% complete
10.5% complete
10.8% complete
11.1% complete
11.4% complete
11.6% complete
11.9% complete
12.2% complete
12.4% complete
12.7% complete
13.0% complete
13.2% complete
13.5% complete
13.8% complete
14.1% complete
14.3% complete
14.6% complete
14.9% complete
15.1% complete
15.4% complete
15.7% complete
15.9% complete
16.2% complete
16.5% complete
16.8% complete
17.0% complete
17.3% complete
17.6% complete
17.8% complete
18.1% complete
18.4% complete
18.6% complete
18.9% complete
19.2% complete
19.5% complete
19.7% complete
20.0% complete
20.3% complete
20.5% complete
20.8% complete
21.1% complete
21.4% complete
21.6% complete
21.9% complete
22.2% complete
22.4% complete
22.7% complete
23.0% complete
23.2% complete
23.5% complete
23.8% complete
24.1% complete
24.3% complete
24.6% complete
24.9% complete
25.1% complete
25.4% complete
25.7% complete
25.9% complete
26.2% complete
26.5% complete
26.8% complete
27.0% complete
27.3% complete
27.6% complete
27.8% complete
28.1% complete
28.4% complete
28.6% complete
28.9% complete
29.2% complete
29.5% complete
29.7% complete
30.0% complete
30.3% complete
30.5% complete
30.8% complete
31.1% complete
31.4% complete
31.6% complete
31.9% complete
32.2% complete
32.4% complete
32.7% complete
33.0% complete
33.2% complete
33.5% complete
33.8% complete
34.1% complete
34.3% complete
34.6% complete
34.9% complete
35.1% complete
35.4% complete
35.7% complete
35.9% complete
36.2% complete
36.5% complete
36.8% complete
37.0% complete
37.3% complete
37.6% complete
37.8% complete
38.1% complete
38.4% complete
38.6% complete
38.9% complete
39.2% complete
39.5% complete
39.7% complete
40.0% complete
40.3% complete
40.5% complete
40.8% complete
41.1% complete
41.4% complete
41.6% complete
41.9% complete
42.2% complete
42.4% complete
42.7% complete
43.0% complete
43.2% complete
43.5% complete
43.8% complete
44.1% complete
44.3% complete
44.6% complete
44.9% complete
45.1% complete
45.4% complete
45.7% complete
45.9% complete
46.2% complete
46.5% complete
46.8% complete
47.0% complete
47.3% complete
47.6% complete
47.8% complete
48.1% complete
48.4% complete
48.6% complete
48.9% complete
49.2% complete
49.5% complete
49.7% complete
50.0% complete
50.3% complete
50.5% complete
50.8% complete
51.1% complete
51.4% complete
51.6% complete
51.9% complete
52.2% complete
52.4% complete
52.7% complete
53.0% complete
53.2% complete
53.5% complete
53.8% complete
54.1% complete
54.3% complete
54.6% complete
54.9% complete
55.1% complete
55.4% complete
55.7% complete
55.9% complete
56.2% complete
56.5% complete
56.8% complete
57.0% complete
57.3% complete
57.6% complete
57.8% complete
58.1% complete
58.4% complete
58.6% complete
58.9% complete
59.2% complete
59.5% complete
59.7% complete
60.0% complete
60.3% complete
60.5% complete
60.8% complete
61.1% complete
61.4% complete
61.6% complete
61.9% complete
62.2% complete
62.4% complete
62.7% complete
63.0% complete
63.2% complete
63.5% complete
63.8% complete
64.1% complete
64.3% complete
64.6% complete
64.9% complete
65.1% complete
65.4% complete
65.7% complete
65.9% complete
66.2% complete
66.5% complete
66.8% complete
67.0% complete
67.3% complete
67.6% complete
67.8% complete
68.1% complete
68.4% complete
68.6% complete
68.9% complete
69.2% complete
69.5% complete
69.7% complete
70.0% complete
70.3% complete
70.5% complete
70.8% complete
71.1% complete
71.4% complete
71.6% complete
71.9% complete
72.2% complete
72.4% complete
72.7% complete
73.0% complete
73.2% complete
73.5% complete
73.8% complete
74.1% complete
74.3% complete
74.6% complete
74.9% complete
75.1% complete
75.4% complete
75.7% complete
75.9% complete
76.2% complete
76.5% complete
76.8% complete
77.0% complete
77.3% complete
77.6% complete
77.8% complete
78.1% complete
78.4% complete
78.6% complete
78.9% complete
79.2% complete
79.5% complete
79.7% complete
80.0% complete
80.3% complete
80.5% complete
80.8% complete
81.1% complete
81.4% complete
81.6% complete
81.9% complete
82.2% complete
82.4% complete
82.7% complete
83.0% complete
83.2% complete
83.5% complete
83.8% complete
84.1% complete
84.3% complete
84.6% complete
84.9% complete
85.1% complete
85.4% complete
85.7% complete
85.9% complete
86.2% complete
86.5% complete
86.8% complete
87.0% complete
87.3% complete
87.6% complete
87.8% complete
88.1% complete
88.4% complete
88.6% complete
88.9% complete
89.2% complete
89.5% complete
89.7% complete
90.0% complete
90.3% complete
90.5% complete
90.8% complete
91.1% complete
91.4% complete
91.6% complete
91.9% complete
92.2% complete
92.4% complete
92.7% complete
93.0% complete
93.2% complete
93.5% complete
93.8% complete
94.1% complete
94.3% complete
94.6% complete
94.9% complete
95.1% complete
95.4% complete
95.7% complete
95.9% complete
96.2% complete
96.5% complete
96.8% complete
97.0% complete
97.3% complete
97.6% complete
97.8% complete
98.1% complete
98.4% complete
98.6% complete
98.9% complete
99.2% complete
99.5% complete
99.7% complete
100.0% complete
                     

The next cell creates a plot of the calculated data. Some of the things you may want to change are:

  • cmap=”Spectral_r”: Change to have different colors

  • plt.title : This will change the plot title.

  • figsize=(16,4) : Change the plot dimensions and/or aspect ratio.

  • vmax=None : This can be set to a numeric value to control the depth scale maximum

  • vmin=0 : This controls the minimum of the depth scale.

  • v_ticks=37 : This changes the number of vertical tick marks

  • h_ticks=10 : This changes the number of horizontal tick marks

  • Unblock the last two lines to ouput the plot as an *.png image file

standoff_series_df=pd.DataFrame({'Tilt': standoff_series[:, 0],'Azimuth': standoff_series[:, 1],'Xₘᵢₙ': standoff_series[:, 2]})
x_fig = plt.figure(figsize=(16,4))
plt.title('Plot of $\it{Xₘᵢₙ}$ for all orientations for $\it{T₉₈}$='+'%.0f' % kwarg_x['T98']+'°C.', fontsize=15, y=1.08)
x_fig=sns.heatmap(standoff_series_df.pivot(index='Tilt', columns='Azimuth', values='Xₘᵢₙ'),
    cbar_kws={'label': 'Xₘᵢₙ', 'format': '%.0f',"pad":0.02 }, cmap="Spectral_r", vmin=0, vmax=None)

h_ticks=37
x_number=math.ceil(360/x_azimuth_step)+1
x_ticks=[(x*(360/(h_ticks-1))/x_azimuth_step+0.5) for x in range(h_ticks-1)]
x_labels=([('%.0f'%(360/(h_ticks-1)*x)) for x in range(h_ticks)])
x_ticks.append(x_number-0.5)
x_fig.set_xticks(x_ticks)
x_fig.set_xticklabels(x_labels, rotation=90);

v_ticks=10
y_number=math.ceil(90/x_tilt_step)+1
y_ticks=[(x*(90/(v_ticks-1))/x_tilt_step+0.5) for x in range(v_ticks-1)]
y_labels=([('%.0f'%(90/(v_ticks-1)*x)) for x in range(v_ticks)])
y_ticks.append(y_number-0.5)
x_fig.set_yticks(y_ticks)
x_fig.set_yticklabels(y_labels, rotation=0);

x_fig.set_xlabel('Azimuth [°]', fontsize=15, labelpad=10);
x_fig.set_ylabel('Tilt [°]', fontsize=15);
x_fig.figure.axes[-1].set_ylabel('$\it{Xₘᵢₙ}$ [cm]', size=15);
x_fig.invert_yaxis()

output_folder = os.path.join(os.path.dirname(os.path.dirname(os.getcwd())), 'TEMP', 'results')
try:
    os.makedirs(output_folder)
except OSError as error:
    print(error)

plt.savefig(os.path.join(output_folder, 'Standoff_Scan.png'), bbox_inches='tight')  #Creates an image file of the standoff plot
plt.show()
../_images/331b0c9e7355b7f23e6c5f8e64ba7062898653deba24172c45a31d1edeca6b2a.png

6. Plot \(T_{98}\) for all azimuth and tilt for a given \(X_{eff}\).#

The temperature of a system is affected by the orientation and the effective standoff, \(X_{eff}\), of the system. This section will scan all possible tilts and azimuths calculating the \(T_{98}\) for a given \(X_{eff}\). As above, additional factors can be modified but are not included here for simplicity. The tilt_step and azimuth_step are the number of degrees for each step for the 90° and 180° tilt and azimuth spans, respectively. The default for this calculation is for \(X_{eff}\)=10 cm, a common effective standoff distance on a rooftop system. A value of \(X_{eff}\)=None will run the calculations for an open rack system and \(X_{eff}\)=0 for an insulated-back system.

#Scans through all the azimuth and tilt running the 98ᵗʰ percentile temperature calculation.
#Set up keyword parameters for the calculation
kwarg_T = dict(sky_model="isotropic", temp_model="sapm", conf_0="insulated_back_glass_polymer", conf_inf="open_rack_glass_polymer",
    x_eff=5, x_0=6.5, wind_factor=0.33)
#Run the calculation
T_azimuth_step=10
T_tilt_step=10
T98_series = pvdeg.utilities.tilt_azimuth_scan(weather_df = WEATHER_df, meta=META,
    tilt_step=T_tilt_step, azimuth_step=T_azimuth_step, func = pvdeg.standards.T98_estimate, **kwarg_T)
0.3% complete
0.5% complete
0.8% complete
1.1% complete
1.4% complete
1.6% complete
1.9% complete
2.2% complete
2.4% complete
2.7% complete
3.0% complete
3.2% complete
3.5% complete
3.8% complete
4.1% complete
4.3% complete
4.6% complete
4.9% complete
5.1% complete
5.4% complete
5.7% complete
5.9% complete
6.2% complete
6.5% complete
6.8% complete
7.0% complete
7.3% complete
7.6% complete
7.8% complete
8.1% complete
8.4% complete
8.6% complete
8.9% complete
9.2% complete
9.5% complete
9.7% complete
10.0% complete
10.3% complete
10.5% complete
10.8% complete
11.1% complete
11.4% complete
11.6% complete
11.9% complete
12.2% complete
12.4% complete
12.7% complete
13.0% complete
13.2% complete
13.5% complete
13.8% complete
14.1% complete
14.3% complete
14.6% complete
14.9% complete
15.1% complete
15.4% complete
15.7% complete
15.9% complete
16.2% complete
16.5% complete
16.8% complete
17.0% complete
17.3% complete
17.6% complete
17.8% complete
18.1% complete
18.4% complete
18.6% complete
18.9% complete
19.2% complete
19.5% complete
19.7% complete
20.0% complete
20.3% complete
20.5% complete
20.8% complete
21.1% complete
21.4% complete
21.6% complete
21.9% complete
22.2% complete
22.4% complete
22.7% complete
23.0% complete
23.2% complete
23.5% complete
23.8% complete
24.1% complete
24.3% complete
24.6% complete
24.9% complete
25.1% complete
25.4% complete
25.7% complete
25.9% complete
26.2% complete
26.5% complete
26.8% complete
27.0% complete
27.3% complete
27.6% complete
27.8% complete
28.1% complete
28.4% complete
28.6% complete
28.9% complete
29.2% complete
29.5% complete
29.7% complete
30.0% complete
30.3% complete
30.5% complete
30.8% complete
31.1% complete
31.4% complete
31.6% complete
31.9% complete
32.2% complete
32.4% complete
32.7% complete
33.0% complete
33.2% complete
33.5% complete
33.8% complete
34.1% complete
34.3% complete
34.6% complete
34.9% complete
35.1% complete
35.4% complete
35.7% complete
35.9% complete
36.2% complete
36.5% complete
36.8% complete
37.0% complete
37.3% complete
37.6% complete
37.8% complete
38.1% complete
38.4% complete
38.6% complete
38.9% complete
39.2% complete
39.5% complete
39.7% complete
40.0% complete
40.3% complete
40.5% complete
40.8% complete
41.1% complete
41.4% complete
41.6% complete
41.9% complete
42.2% complete
42.4% complete
42.7% complete
43.0% complete
43.2% complete
43.5% complete
43.8% complete
44.1% complete
44.3% complete
44.6% complete
44.9% complete
45.1% complete
45.4% complete
45.7% complete
45.9% complete
46.2% complete
46.5% complete
46.8% complete
47.0% complete
47.3% complete
47.6% complete
47.8% complete
48.1% complete
48.4% complete
48.6% complete
48.9% complete
49.2% complete
49.5% complete
49.7% complete
50.0% complete
50.3% complete
50.5% complete
50.8% complete
51.1% complete
51.4% complete
51.6% complete
51.9% complete
52.2% complete
52.4% complete
52.7% complete
53.0% complete
53.2% complete
53.5% complete
53.8% complete
54.1% complete
54.3% complete
54.6% complete
54.9% complete
55.1% complete
55.4% complete
55.7% complete
55.9% complete
56.2% complete
56.5% complete
56.8% complete
57.0% complete
57.3% complete
57.6% complete
57.8% complete
58.1% complete
58.4% complete
58.6% complete
58.9% complete
59.2% complete
59.5% complete
59.7% complete
60.0% complete
60.3% complete
60.5% complete
60.8% complete
61.1% complete
61.4% complete
61.6% complete
61.9% complete
62.2% complete
62.4% complete
62.7% complete
63.0% complete
63.2% complete
63.5% complete
63.8% complete
64.1% complete
64.3% complete
64.6% complete
64.9% complete
65.1% complete
65.4% complete
65.7% complete
65.9% complete
66.2% complete
66.5% complete
66.8% complete
67.0% complete
67.3% complete
67.6% complete
67.8% complete
68.1% complete
68.4% complete
68.6% complete
68.9% complete
69.2% complete
69.5% complete
69.7% complete
70.0% complete
70.3% complete
70.5% complete
70.8% complete
71.1% complete
71.4% complete
71.6% complete
71.9% complete
72.2% complete
72.4% complete
72.7% complete
73.0% complete
73.2% complete
73.5% complete
73.8% complete
74.1% complete
74.3% complete
74.6% complete
74.9% complete
75.1% complete
75.4% complete
75.7% complete
75.9% complete
76.2% complete
76.5% complete
76.8% complete
77.0% complete
77.3% complete
77.6% complete
77.8% complete
78.1% complete
78.4% complete
78.6% complete
78.9% complete
79.2% complete
79.5% complete
79.7% complete
80.0% complete
80.3% complete
80.5% complete
80.8% complete
81.1% complete
81.4% complete
81.6% complete
81.9% complete
82.2% complete
82.4% complete
82.7% complete
83.0% complete
83.2% complete
83.5% complete
83.8% complete
84.1% complete
84.3% complete
84.6% complete
84.9% complete
85.1% complete
85.4% complete
85.7% complete
85.9% complete
86.2% complete
86.5% complete
86.8% complete
87.0% complete
87.3% complete
87.6% complete
87.8% complete
88.1% complete
88.4% complete
88.6% complete
88.9% complete
89.2% complete
89.5% complete
89.7% complete
90.0% complete
90.3% complete
90.5% complete
90.8% complete
91.1% complete
91.4% complete
91.6% complete
91.9% complete
92.2% complete
92.4% complete
92.7% complete
93.0% complete
93.2% complete
93.5% complete
93.8% complete
94.1% complete
94.3% complete
94.6% complete
94.9% complete
95.1% complete
95.4% complete
95.7% complete
95.9% complete
96.2% complete
96.5% complete
96.8% complete
97.0% complete
97.3% complete
97.6% complete
97.8% complete
98.1% complete
98.4% complete
98.6% complete
98.9% complete
99.2% complete
99.5% complete
99.7% complete
100.0% complete
                     

The next cell creates a plot of the calculated data. Some of the things you may want to change are:

  • cmap=”Spectral_r”: Change to have different colors

  • plt.title : This will change the plot title.

  • figsize=(16,4) : Change the plot dimensions and/or aspect ratio.

  • vmax=None : This can be set to a numeric value to control the depth scale maximum

  • vmin=None : This controls the minimum of the depth scale.

  • v_ticks=37 : This changes the number of vertical tick marks

  • h_ticks=10 : This changes the number of horizontal tick marks

  • Unblock the last two lines to ouput the plot as an *.png image file

#This produces the plot of the data
T98_series_df=pd.DataFrame({'Tilt': T98_series[:, 0],'Azimuth': T98_series[:, 1],'T₉₈': T98_series[:, 2]})
T98_fig = plt.figure(figsize=(16,4))
if kwarg_T['x_eff']==None:
    plt.title('Plot of $\it{T₉₈}$ for all orientations for an open-rack mounting.', fontsize=15, y=1.08)
else:
    plt.title('Plot of $\it{T₉₈}$ for all orientations for $X_{eff}$='+'%.0f' % kwarg_T['x_eff']+' cm.', fontsize=15, y=1.08)
T98_fig=sns.heatmap(T98_series_df.pivot(index='Tilt', columns='Azimuth', values='T₉₈'),
    cbar_kws={'label': 'Xₘᵢₙ', 'format': '%.0f',"pad":0.02 }, cmap="Spectral_r", vmin=None, vmax=None)

h_ticks=37
x_number=math.ceil(360/T_azimuth_step)+1
x_ticks=[(x*(360/(h_ticks-1))/T_azimuth_step+0.5) for x in range(h_ticks-1)]
x_labels=([('%.0f'%(360/(h_ticks-1)*x)) for x in range(h_ticks)])
x_ticks.append(x_number-0.5)
T98_fig.set_xticks(x_ticks)
T98_fig.set_xticklabels(x_labels, rotation=90);

v_ticks=10
y_number=math.ceil(90/T_tilt_step)+1
y_ticks=[(x*(90/(v_ticks-1))/T_tilt_step+0.5) for x in range(v_ticks-1)]
y_labels=([('%.0f'%(90/(v_ticks-1)*x)) for x in range(v_ticks)])
y_ticks.append(y_number-0.5)
T98_fig.set_yticks(y_ticks)
T98_fig.set_yticklabels(y_labels, rotation=0);

T98_fig.set_xlabel('Azimuth [°]', fontsize=15, labelpad=10);
T98_fig.set_ylabel('Tilt [°]', fontsize=15);
T98_fig.figure.axes[-1].set_ylabel('$\it{T₉₈}$ [°C]', size=15);
T98_fig.invert_yaxis()

plt.savefig(os.path.join(output_folder, 'T98_Scan.png'), bbox_inches='tight')  #Creates an image file of the standoff plot
plt.show(T98_fig)
../_images/2a2db535fbf81d06f83d17871bb44c630ff9461984d89bad08a360d51092a23d.png

7. Plot \(X_{min}\) for a \(T_{98}\), and plot \(T_{98}\) for a given region.#

This last Objective is much more complicated and is set up to utilize acess to a lot of computational power to run many sites simultaneously to create a regional map of standoff distance. For more in-depth instructions on doing this, look at the tutorial “Scenario - Geospatial.ipynb” here in PVDeg.

Step #1: Create an object, “geospatial_standoff_scenario” to be used to run the computations.

geospatial_standoff_scenario = pvdeg.scenario.Geospatial_Scenario(
    name='standoff geospatial',
    geospatial = True,
) 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[14], line 1
----> 1 geospatial_standoff_scenario = pvdeg.scenario.Geospatial_Scenario(
      2     name='standoff geospatial',
      3     geospatial = True,
      4 ) 

AttributeError: module 'pvdeg.scenario' has no attribute 'Geospatial_Scenario'

Step #2: Identifies a subset of locations from the database to run the computations. Specifically all are from the NSRDB. “see_added” if true will show the Geographical Identification numbers (GID) of the meterological data sets that were identified.

geospatial_standoff_scenario.addLocation(
    state='Colorado',
    county='Summit',
    see_added=True
) # Identifies a subset of locations from the database to run the computations. Specifically all are from the NSRDB.

Step #3: indicate which function will be run. Here the default is the standoff calculation, but it could be any other function with a key word argument dictionary. Here the 98th percential temperature is defined as 70C, but any arbitrary value can be specified.

geospatial_standoff_scenario.addJob(
    func=pvdeg.standards.standoff,
    func_params = {"T98": 70},
    see_added=True
)

Step #4: Run the scenario

geospatial_standoff_scenario.run()

Step #5: Create a plot of the standoff calculation.

geospatial_standoff_scenario.plot_world('x')
geospatial_standoff_scenario.plot_world('T98_inf')

8. Save data outputs.#

This cell contains a number of pre-scripted commands for exporting and saving data. The code to save plots is located after the plot creation and is blocked by default. First check that the output folder exists, then unblock the code for data you would like to save.

print ("Your results will be stored in %s" % output_folder)
print ('The folder must already exist or the file will not be created')

pvdeg.weather.write(data_df=WEATHER_df, metadata=META, savefile=os.path.join(output_folder, 'WeatherFile.csv')) #Writes the meterological data to an *.csv file.

pd.DataFrame(standoff_series_df).to_csv(os.path.join(output_folder, 'Standoff_Scan.csv')) #Writes a file with the Tilt and Azimuth scan calculations of standoff.

pd.DataFrame(T98_series_df).to_csv(os.path.join(output_folder, 'T98_Scan.csv')) #Writes a file with the Tilt and Azimuth scan calculations of T98.
Your results will be stored in c:\Users\mkempe\Documents\GitHub\PVDegradationTools\TEMP\results
The folder must already exist or the file will not be created