Skip to content

restructure pvlib/spectrum #2136

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 12 commits into from
Aug 5, 2024
5 changes: 4 additions & 1 deletion docs/sphinx/source/whatsnew/v0.11.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Enhancements
* Add new parameters for min/max absolute air mass to
:py:func:`pvlib.spectrum.spectral_factor_firstsolar`.
(:issue:`2086`, :pull:`2100`)

* Restructured the pvlib/spectrum folder by breaking up the contents of
pvlib/spectrum/mismatch.py into pvlib/spectrum/mismatch.py,
pvlib/spectrum/irradiance.py, and
pvlib/spectrum/response.py. (:issue:`2125`, :pull:`2136`)
* Added function for calculating wind speed at different heights,
:py:func:`pvlib.atmosphere.windspeed_powerlaw`.
(:issue:`2118`, :pull:`2124`)
Expand Down
12 changes: 8 additions & 4 deletions pvlib/spectrum/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from pvlib.spectrum.spectrl2 import spectrl2 # noqa: F401
from pvlib.spectrum.mismatch import ( # noqa: F401
calc_spectral_mismatch_field,
get_am15g,
get_reference_spectra,
get_example_spectral_response,
spectral_factor_caballero,
spectral_factor_firstsolar,
spectral_factor_sapm,
spectral_factor_pvspec,
spectral_factor_jrc,
)
from pvlib.spectrum.irradiance import ( # noqa: F401
get_am15g,
get_reference_spectra,
)
from pvlib.spectrum.response import ( # noqa: F401
get_example_spectral_response,
sr_to_qe,
qe_to_sr
qe_to_sr,
)
178 changes: 178 additions & 0 deletions pvlib/spectrum/irradiance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
"""
The ``irradiance`` module in the ``spectrum`` package provides functions for
calculations related to spectral irradiance data.
"""

import pvlib
from pvlib._deprecation import deprecated
import numpy as np
import pandas as pd
from pathlib import Path
from functools import partial


@deprecated(
since="0.11",
removal="0.12",
name="pvlib.spectrum.get_am15g",
alternative="pvlib.spectrum.get_reference_spectra",
addendum=(
"The new function reads more data. Use it with "
+ "standard='ASTM G173-03' and extract the 'global' column."
),
)
def get_am15g(wavelength=None):
r"""
Read the ASTM G173-03 AM1.5 global spectrum on a 37-degree tilted surface,
optionally interpolated to the specified wavelength(s).

Global (tilted) irradiance includes direct and diffuse irradiance from sky
and ground reflections, and is more formally called hemispherical
irradiance (on a tilted surface). In the context of photovoltaic systems
the irradiance on a flat receiver is frequently called plane-of-array (POA)
irradiance.

Parameters
----------
wavelength: 1-D sequence of numeric, optional
Wavelengths at which the spectrum is interpolated.
By default the 2002 wavelengths of the standard are returned. [nm].

Returns
-------
am15g: pandas.Series
The AM1.5g standard spectrum indexed by ``wavelength``. [W/(m²nm)].

Notes
-----
If ``wavelength`` is specified this function uses linear interpolation.

If the values in ``wavelength`` are too widely spaced, the integral of the
spectrum may deviate from the standard value of 1000.37 W/m².

The values in the data file provided with pvlib-python are copied from an
Excel file distributed by NREL, which is found here:
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls

More information about reference spectra is found here:
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html

See Also
--------
pvlib.spectrum.get_reference_spectra : reads also the direct and
extraterrestrial components of the spectrum.

References
----------
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
""" # noqa: E501
# Contributed by Anton Driesse (@adriesse), PV Performance Labs. Aug. 2022
# modified by @echedey-ls, as a wrapper of spectrum.get_reference_spectra
standard = get_reference_spectra(wavelength, standard="ASTM G173-03")
return standard["global"]


def get_reference_spectra(wavelengths=None, standard="ASTM G173-03"):
r"""
Read a standard spectrum specified by ``standard``, optionally
interpolated to the specified wavelength(s).

Defaults to ``ASTM G173-03`` AM1.5 standard [1]_, which returns
``extraterrestrial``, ``global`` and ``direct`` spectrum on a 37-degree
tilted surface, optionally interpolated to the specified wavelength(s).

Parameters
----------
wavelengths : numeric, optional
Wavelengths at which the spectrum is interpolated. [nm].
If not provided, the original wavelengths from the specified standard
are used. Values outside that range are filled with zeros.

standard : str, default "ASTM G173-03"
The reference standard to be read. Only the reference
``"ASTM G173-03"`` is available at the moment.

Returns
-------
standard_spectra : pandas.DataFrame
The standard spectrum by ``wavelength [nm]``. [W/(m²nm)].
Column names are ``extraterrestrial``, ``direct`` and ``global``.

Notes
-----
If ``wavelength`` is specified, linear interpolation is used.

If the values in ``wavelength`` are too widely spaced, the integral of each
spectrum may deviate from its standard value.
For global spectra, it is about 1000.37 W/m².

The values of the ASTM G173-03 provided with pvlib-python are copied from
an Excel file distributed by NREL, which is found here [2]_:
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls

Examples
--------
>>> from pvlib import spectrum
>>> am15 = spectrum.get_reference_spectra()
>>> am15_extraterrestrial, am15_global, am15_direct = \
>>> am15['extraterrestrial'], am15['global'], am15['direct']
>>> print(am15.head())
extraterrestrial global direct
wavelength
280.0 0.082 4.730900e-23 2.536100e-26
280.5 0.099 1.230700e-21 1.091700e-24
281.0 0.150 5.689500e-21 6.125300e-24
281.5 0.212 1.566200e-19 2.747900e-22
282.0 0.267 1.194600e-18 2.834600e-21

>>> am15 = spectrum.get_reference_spectra([300, 500, 800, 1100])
>>> print(am15)
extraterrestrial global direct
wavelength
300 0.45794 0.00102 0.000456
500 1.91600 1.54510 1.339100
800 1.12480 1.07250 0.988590
1100 0.60000 0.48577 0.461130

References
----------
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
.. [2] “Reference Air Mass 1.5 Spectra,” www.nrel.gov.
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
""" # Contributed by Echedey Luis, inspired by Anton Driesse (get_am15g)
SPECTRA_FILES = {
"ASTM G173-03": "ASTMG173.csv",
}
pvlib_datapath = Path(pvlib.__path__[0]) / "data"

try:
filepath = pvlib_datapath / SPECTRA_FILES[standard]
except KeyError:
raise ValueError(
f"Invalid standard identifier '{standard}'. Available "
+ "identifiers are: "
+ ", ".join(SPECTRA_FILES.keys())
)

standard = pd.read_csv(
filepath,
header=1, # expect first line of description, then column names
index_col=0, # first column is "wavelength"
dtype=float,
)

if wavelengths is not None:
interpolator = partial(
np.interp, xp=standard.index, left=0.0, right=0.0
)
standard = pd.DataFrame(
index=wavelengths,
data={
col: interpolator(x=wavelengths, fp=standard[col])
for col in standard.columns
},
)

return standard
Loading
Loading