Skip to content

Commit 72185cb

Browse files
authored
restructure pvlib/spectrum (#2136)
* restructure pvlib/spectrum update __init__.py rename mismatch.py to spectral_mismatch.py create spectral_irradiance.py, spectral_response.py * update irr and mismatch * update irr mismatch * Update __init__.py * Update spectral_mismatch.py resolve circular imports (attempt) * Update spectral_mismatch.py * Update spectral_mismatch.py * Update v0.11.1.rst * Update v0.11.1.rst breaking -> breaking up * remove spectral prefix * update file names
1 parent f6b1d2a commit 72185cb

File tree

5 files changed

+477
-454
lines changed

5 files changed

+477
-454
lines changed

docs/sphinx/source/whatsnew/v0.11.1.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ Enhancements
1616
* Add new parameters for min/max absolute air mass to
1717
:py:func:`pvlib.spectrum.spectral_factor_firstsolar`.
1818
(:issue:`2086`, :pull:`2100`)
19-
19+
* Restructured the pvlib/spectrum folder by breaking up the contents of
20+
pvlib/spectrum/mismatch.py into pvlib/spectrum/mismatch.py,
21+
pvlib/spectrum/irradiance.py, and
22+
pvlib/spectrum/response.py. (:issue:`2125`, :pull:`2136`)
2023
* Added function for calculating wind speed at different heights,
2124
:py:func:`pvlib.atmosphere.windspeed_powerlaw`.
2225
(:issue:`2118`, :pull:`2124`)

pvlib/spectrum/__init__.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
from pvlib.spectrum.spectrl2 import spectrl2 # noqa: F401
22
from pvlib.spectrum.mismatch import ( # noqa: F401
33
calc_spectral_mismatch_field,
4-
get_am15g,
5-
get_reference_spectra,
6-
get_example_spectral_response,
74
spectral_factor_caballero,
85
spectral_factor_firstsolar,
96
spectral_factor_sapm,
107
spectral_factor_pvspec,
118
spectral_factor_jrc,
9+
)
10+
from pvlib.spectrum.irradiance import ( # noqa: F401
11+
get_am15g,
12+
get_reference_spectra,
13+
)
14+
from pvlib.spectrum.response import ( # noqa: F401
15+
get_example_spectral_response,
1216
sr_to_qe,
13-
qe_to_sr
17+
qe_to_sr,
1418
)

pvlib/spectrum/irradiance.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
"""
2+
The ``irradiance`` module in the ``spectrum`` package provides functions for
3+
calculations related to spectral irradiance data.
4+
"""
5+
6+
import pvlib
7+
from pvlib._deprecation import deprecated
8+
import numpy as np
9+
import pandas as pd
10+
from pathlib import Path
11+
from functools import partial
12+
13+
14+
@deprecated(
15+
since="0.11",
16+
removal="0.12",
17+
name="pvlib.spectrum.get_am15g",
18+
alternative="pvlib.spectrum.get_reference_spectra",
19+
addendum=(
20+
"The new function reads more data. Use it with "
21+
+ "standard='ASTM G173-03' and extract the 'global' column."
22+
),
23+
)
24+
def get_am15g(wavelength=None):
25+
r"""
26+
Read the ASTM G173-03 AM1.5 global spectrum on a 37-degree tilted surface,
27+
optionally interpolated to the specified wavelength(s).
28+
29+
Global (tilted) irradiance includes direct and diffuse irradiance from sky
30+
and ground reflections, and is more formally called hemispherical
31+
irradiance (on a tilted surface). In the context of photovoltaic systems
32+
the irradiance on a flat receiver is frequently called plane-of-array (POA)
33+
irradiance.
34+
35+
Parameters
36+
----------
37+
wavelength: 1-D sequence of numeric, optional
38+
Wavelengths at which the spectrum is interpolated.
39+
By default the 2002 wavelengths of the standard are returned. [nm].
40+
41+
Returns
42+
-------
43+
am15g: pandas.Series
44+
The AM1.5g standard spectrum indexed by ``wavelength``. [W/(m²nm)].
45+
46+
Notes
47+
-----
48+
If ``wavelength`` is specified this function uses linear interpolation.
49+
50+
If the values in ``wavelength`` are too widely spaced, the integral of the
51+
spectrum may deviate from the standard value of 1000.37 W/m².
52+
53+
The values in the data file provided with pvlib-python are copied from an
54+
Excel file distributed by NREL, which is found here:
55+
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
56+
57+
More information about reference spectra is found here:
58+
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
59+
60+
See Also
61+
--------
62+
pvlib.spectrum.get_reference_spectra : reads also the direct and
63+
extraterrestrial components of the spectrum.
64+
65+
References
66+
----------
67+
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
68+
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
69+
""" # noqa: E501
70+
# Contributed by Anton Driesse (@adriesse), PV Performance Labs. Aug. 2022
71+
# modified by @echedey-ls, as a wrapper of spectrum.get_reference_spectra
72+
standard = get_reference_spectra(wavelength, standard="ASTM G173-03")
73+
return standard["global"]
74+
75+
76+
def get_reference_spectra(wavelengths=None, standard="ASTM G173-03"):
77+
r"""
78+
Read a standard spectrum specified by ``standard``, optionally
79+
interpolated to the specified wavelength(s).
80+
81+
Defaults to ``ASTM G173-03`` AM1.5 standard [1]_, which returns
82+
``extraterrestrial``, ``global`` and ``direct`` spectrum on a 37-degree
83+
tilted surface, optionally interpolated to the specified wavelength(s).
84+
85+
Parameters
86+
----------
87+
wavelengths : numeric, optional
88+
Wavelengths at which the spectrum is interpolated. [nm].
89+
If not provided, the original wavelengths from the specified standard
90+
are used. Values outside that range are filled with zeros.
91+
92+
standard : str, default "ASTM G173-03"
93+
The reference standard to be read. Only the reference
94+
``"ASTM G173-03"`` is available at the moment.
95+
96+
Returns
97+
-------
98+
standard_spectra : pandas.DataFrame
99+
The standard spectrum by ``wavelength [nm]``. [W/(m²nm)].
100+
Column names are ``extraterrestrial``, ``direct`` and ``global``.
101+
102+
Notes
103+
-----
104+
If ``wavelength`` is specified, linear interpolation is used.
105+
106+
If the values in ``wavelength`` are too widely spaced, the integral of each
107+
spectrum may deviate from its standard value.
108+
For global spectra, it is about 1000.37 W/m².
109+
110+
The values of the ASTM G173-03 provided with pvlib-python are copied from
111+
an Excel file distributed by NREL, which is found here [2]_:
112+
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
113+
114+
Examples
115+
--------
116+
>>> from pvlib import spectrum
117+
>>> am15 = spectrum.get_reference_spectra()
118+
>>> am15_extraterrestrial, am15_global, am15_direct = \
119+
>>> am15['extraterrestrial'], am15['global'], am15['direct']
120+
>>> print(am15.head())
121+
extraterrestrial global direct
122+
wavelength
123+
280.0 0.082 4.730900e-23 2.536100e-26
124+
280.5 0.099 1.230700e-21 1.091700e-24
125+
281.0 0.150 5.689500e-21 6.125300e-24
126+
281.5 0.212 1.566200e-19 2.747900e-22
127+
282.0 0.267 1.194600e-18 2.834600e-21
128+
129+
>>> am15 = spectrum.get_reference_spectra([300, 500, 800, 1100])
130+
>>> print(am15)
131+
extraterrestrial global direct
132+
wavelength
133+
300 0.45794 0.00102 0.000456
134+
500 1.91600 1.54510 1.339100
135+
800 1.12480 1.07250 0.988590
136+
1100 0.60000 0.48577 0.461130
137+
138+
References
139+
----------
140+
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
141+
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
142+
.. [2] “Reference Air Mass 1.5 Spectra,” www.nrel.gov.
143+
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
144+
""" # Contributed by Echedey Luis, inspired by Anton Driesse (get_am15g)
145+
SPECTRA_FILES = {
146+
"ASTM G173-03": "ASTMG173.csv",
147+
}
148+
pvlib_datapath = Path(pvlib.__path__[0]) / "data"
149+
150+
try:
151+
filepath = pvlib_datapath / SPECTRA_FILES[standard]
152+
except KeyError:
153+
raise ValueError(
154+
f"Invalid standard identifier '{standard}'. Available "
155+
+ "identifiers are: "
156+
+ ", ".join(SPECTRA_FILES.keys())
157+
)
158+
159+
standard = pd.read_csv(
160+
filepath,
161+
header=1, # expect first line of description, then column names
162+
index_col=0, # first column is "wavelength"
163+
dtype=float,
164+
)
165+
166+
if wavelengths is not None:
167+
interpolator = partial(
168+
np.interp, xp=standard.index, left=0.0, right=0.0
169+
)
170+
standard = pd.DataFrame(
171+
index=wavelengths,
172+
data={
173+
col: interpolator(x=wavelengths, fp=standard[col])
174+
for col in standard.columns
175+
},
176+
)
177+
178+
return standard

0 commit comments

Comments
 (0)