From c9b860cd2e164f75e8c9a4d83528dc67daeb1e3b Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 1 Jul 2024 21:26:42 +0100 Subject: [PATCH 01/37] Create spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 141 ++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 docs/examples/spectrum/spectral_factor.py diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py new file mode 100644 index 0000000000..f327ec8140 --- /dev/null +++ b/docs/examples/spectrum/spectral_factor.py @@ -0,0 +1,141 @@ +""" +Spectral Mismatch Estimation +============================ +Comparison of spectral factor calculation methods used to estimate the spectral +mismatch factor from atmopsheric variable inputs. +""" + +# %% +# Introduction +# ------------ +# This example demonstrates how to use different `spectrum.spectral_factor` +# models in pvlib to calculate the spectral mismatch factor, :math:`M`. While +# :math:`M` for a photovoltaic (PV) module can be calculated exactly using +# spectral irradiance and module spectral response data, these data are not +# always available. pvlib provides several functions to estimate the spectral +# mismatch factor, :math:`M`, using proxies of the prevaiing spectral +# irradiance conditions, such as air mass and clearsky index, which are easily +# derived from common ground-based measurements such as broadband irradiance. +# More information on a range of spectral factor models, as wel as the +# variables upon which they are based, can be found in [1]_. + +from matplotlib import pyplot as plt +import pandas as pd +import pvlib as pv +from pvlib import location +from pvlib.solarposition import get_solarposition +from pvlib.atmosphere import get_relative_airmass + +# Let's import some data. This example uses a Typical Meteorological Year 3 +# (TMY3) file for the +# location of Greensboro, North Carolina, from the pvlib data directory. This +# TMY3 file is constructed using the median month from each year between 1980 +# and 2003, from which we extract the first week of August 2001 to analyse. +meteo, metadata = pv.iotools.read_tmy3( + r'C:\Users\ezxrd3\Documents\GitHub\pvlib-python\pvlib\data\723170TYA.csv', + map_variables=True) +meteo = meteo.sort_index() +meteo = meteo.between_time('06:00', '20:00').loc['2001-08-01':'2001-08-07'] + +# %% +# pvlib Spectral Factor Functions +# ----------------------------- +# This example demonstrates the application of three pvlib spectral factor +# functions, namely `sapm`_, `pvspec`, and `firstsolar`_. + +# %% +# SAPM +# ---- +# The SAPM function for the spectral mismatch +# factor calculates :math:`M` using absolute airmass, :math:`AM_a` as an input. + +# %% +# PVSPEC +# ------ +# The PVSPEC function for the spectral mismatch factor calculates :math:`M` +# using :math:`AM_a` and the clearsky index, :math:`k_c` as inputs. + +# %% +# First Solar +# ----------- +# The First Solar function for the spectral mismatch factor calculates +# :math:`M` using :math:`AM_a` and the atmospheric precipitable water content, +# :math:`W`, as inputs. + +# %% +# Calculation of inputs +# --------------------- +# Let's calculate the absolute air mass, which is required for all three +# models. We use the Kasten and Young [2]_ model, which requires the apparent +# sun zenith. Note: TMY3 files timestamps indicate the end of the hour, so we +# shift the indices back 30-minutes to calculate solar position at the centre +# of the interval. + +# Create a location object +lat, lon = metadata['latitude'], metadata['longitude'] +alt = altitude = metadata['altitude'] +tz = 'Etc/GMT+5' +loc = location.Location(lat, lon, tz=tz, name='Greensboro, NC') + +# Calculate solar position parameters +solpos = get_solarposition( + meteo.index.shift(freq="-30min"), lat, lon, alt, + pressure=meteo.pressure*100, # convert from millibar to Pa + temperature=meteo.temp_air) +solpos.index = meteo.index # reset index to end of the hour + +amr = get_relative_airmass(solpos.apparent_zenith).dropna() # relative airmass +ama = amr*(meteo.pressure/1013.25) # absolute airmass + +# Now we calculate the clearsky index, :math:`kc`, by comparing the TMY3 GHI to +# the modelled clearky GHI. + +cs = loc.get_clearsky(meteo.index) +kc = cs.ghi/meteo.ghi + +# :math:`W` is provided in the TMY3 file but in other cases can be calculated +# from temperature and relative humidity. + +w = meteo.precipitable_water + +# %% +# Calculation of Spectral Mismatch + +# Let's calculate the spectral mismatch factor using the three pvlib functions. +# First, we need to import some model coefficients for the SAPM spectral factor +# function, which, unlike the other two functions, lacks built-in coefficients. + +# Import some for a mc-Si module from the SAPM module database. +module = pv.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] +# Calculate :math:`M` using the three models for an mc-Si PV module. +m_sapm = pv.spectrum.spectral_factor_sapm(ama, module) +m_pvspec = pv.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') +m_fs = pv.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') +df_results = pd.concat([m_sapm, m_pvspec, m_fs], axis=1) +df_results.columns = ['SAPM', 'PVSPEC', 'FS'] +# %% +# Comparison Plots + +# We can plot the results to visualisee variability between the models. Note +# that this is not an exact comparison since the exact same PV modules has +# not been modelled in each case, only the same module technology. + +# Convert Dataframe Indexes to Month-Day our:Minute format +df_results.index = df_results.index.strftime("%m-%d") + +# Plot :math:`M` +fig1, ax1 = plt.subplots() +df_results.plot(ax=ax1) + +ax1.set_xlabel('Date (m-d H:M)') +ax1.set_ylabel('Mismatch (-)') +ax1.legend() +plt.show() + +# We can also zoom in one one day, for example August 1st. +df_results.index = m_fs.index +df_results = df_results.loc['2001-08-01':'2001-08-01'] +df_results.index = df_results.index.strftime("%H:%M") +fig2, ax1 = plt.subplots() +df_results.plot(ax=ax1) +plt.show() From d1156beb07734e7e327b3d42be03cc4262bb0a86 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:43:12 +0100 Subject: [PATCH 02/37] Update spectral_factor.py fix directory, add refs --- docs/examples/spectrum/spectral_factor.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index f327ec8140..c24092cba5 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -16,9 +16,10 @@ # mismatch factor, :math:`M`, using proxies of the prevaiing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. -# More information on a range of spectral factor models, as wel as the +# More information on a range of spectral factor models, as well as the # variables upon which they are based, can be found in [1]_. +import pathlib from matplotlib import pyplot as plt import pandas as pd import pvlib as pv @@ -31,9 +32,9 @@ # location of Greensboro, North Carolina, from the pvlib data directory. This # TMY3 file is constructed using the median month from each year between 1980 # and 2003, from which we extract the first week of August 2001 to analyse. -meteo, metadata = pv.iotools.read_tmy3( - r'C:\Users\ezxrd3\Documents\GitHub\pvlib-python\pvlib\data\723170TYA.csv', - map_variables=True) +DATA_DIR = pathlib.Path(pv.__file__).parent / 'data' +meteo, metadata = pv.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', + map_variables=True) meteo = meteo.sort_index() meteo = meteo.between_time('06:00', '20:00').loc['2001-08-01':'2001-08-07'] @@ -139,3 +140,15 @@ fig2, ax1 = plt.subplots() df_results.plot(ax=ax1) plt.show() + +""" +References +---------- +.. [1] Daxini, Rajiv, and Yupeng Wu (2023). "Review of methods to account for + the solar spectral influence on photovoltaic device performance." Energy + 286 + :doi:`10.1364/AO.28.004735` +.. [2] Kasten, F. and Young, A.T., 1989. Revised optical air mass tables + and approximation formula. Applied Optics, 28(22), pp.4735-4738. + :doi:`10.1364/AO.28.004735` +""" From 8fefcf2f89bc98c711cca18ee6532b13551f469c Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:13:27 +0100 Subject: [PATCH 03/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 53 ++++++++++++----------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index c24092cba5..76bab9aa38 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -19,6 +19,12 @@ # More information on a range of spectral factor models, as well as the # variables upon which they are based, can be found in [1]_. +# Let's import some data. This example uses a Typical Meteorological Year 3 +# (TMY3) file for the +# location of Greensboro, North Carolina, from the pvlib data directory. This +# TMY3 file is constructed using the median month from each year between 1980 +# and 2003, from which we extract the first week of August 2001 to analyse. + import pathlib from matplotlib import pyplot as plt import pandas as pd @@ -27,11 +33,6 @@ from pvlib.solarposition import get_solarposition from pvlib.atmosphere import get_relative_airmass -# Let's import some data. This example uses a Typical Meteorological Year 3 -# (TMY3) file for the -# location of Greensboro, North Carolina, from the pvlib data directory. This -# TMY3 file is constructed using the median month from each year between 1980 -# and 2003, from which we extract the first week of August 2001 to analyse. DATA_DIR = pathlib.Path(pv.__file__).parent / 'data' meteo, metadata = pv.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', map_variables=True) @@ -42,26 +43,28 @@ # pvlib Spectral Factor Functions # ----------------------------- # This example demonstrates the application of three pvlib spectral factor -# functions, namely `sapm`_, `pvspec`, and `firstsolar`_. +# functions, namely `SAPM`_, `PVSPEC`_, and `firstsolar`_. # %% # SAPM # ---- -# The SAPM function for the spectral mismatch -# factor calculates :math:`M` using absolute airmass, :math:`AM_a` as an input. +# The SAPM function (:py:func:`pvlib.spectrum.spectral_factor_sapm`) for the +# spectral mismatch factor calculates :math:`M` using absolute airmass, +# :math:`AM_a` as an input. # %% # PVSPEC # ------ -# The PVSPEC function for the spectral mismatch factor calculates :math:`M` -# using :math:`AM_a` and the clearsky index, :math:`k_c` as inputs. +# The PVSPEC function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) for +# the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and the +# clearsky index, :math:`k_c` as inputs. # %% # First Solar # ----------- -# The First Solar function for the spectral mismatch factor calculates -# :math:`M` using :math:`AM_a` and the atmospheric precipitable water content, -# :math:`W`, as inputs. +# The First Solar function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) +# for the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and +# the atmospheric precipitable water content, :math:`W`, as inputs. # %% # Calculation of inputs @@ -101,6 +104,7 @@ # %% # Calculation of Spectral Mismatch +# -------------------------------- # Let's calculate the spectral mismatch factor using the three pvlib functions. # First, we need to import some model coefficients for the SAPM spectral factor @@ -116,7 +120,7 @@ df_results.columns = ['SAPM', 'PVSPEC', 'FS'] # %% # Comparison Plots - +# ---------------- # We can plot the results to visualisee variability between the models. Note # that this is not an exact comparison since the exact same PV modules has # not been modelled in each case, only the same module technology. @@ -141,14 +145,13 @@ df_results.plot(ax=ax1) plt.show() -""" -References ----------- -.. [1] Daxini, Rajiv, and Yupeng Wu (2023). "Review of methods to account for - the solar spectral influence on photovoltaic device performance." Energy - 286 - :doi:`10.1364/AO.28.004735` -.. [2] Kasten, F. and Young, A.T., 1989. Revised optical air mass tables - and approximation formula. Applied Optics, 28(22), pp.4735-4738. - :doi:`10.1364/AO.28.004735` -""" +# %% +# References +# ---------- +# .. [1] Daxini, Rajiv, and Yupeng Wu (2023). "Review of methods to account for +# the solar spectral influence on photovoltaic device performance." +# Energy 286 +# :doi:`10.1364/AO.28.004735` +# .. [2] Kasten, F. and Young, A.T., 1989. Revised optical air mass tables +# and approximation formula. Applied Optics, 28(22), pp.4735-4738. +# :doi:`10.1364/AO.28.004735` From c566795912ffe7c5e4d8337d6177be239ce5df56 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:34:16 +0100 Subject: [PATCH 04/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 76bab9aa38..83e517207a 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -24,7 +24,7 @@ # location of Greensboro, North Carolina, from the pvlib data directory. This # TMY3 file is constructed using the median month from each year between 1980 # and 2003, from which we extract the first week of August 2001 to analyse. - +# %% import pathlib from matplotlib import pyplot as plt import pandas as pd @@ -62,7 +62,8 @@ # %% # First Solar # ----------- -# The First Solar function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) +# The First Solar function (:py:func:`pvlib.spectrum.spectral_factor_firstsolar +# `) # for the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and # the atmospheric precipitable water content, :math:`W`, as inputs. From e8b63ec0053040e14d3d3afa787a263b6f8ee539 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:50:36 +0100 Subject: [PATCH 05/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 83e517207a..b9df47c9f1 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -20,10 +20,11 @@ # variables upon which they are based, can be found in [1]_. # Let's import some data. This example uses a Typical Meteorological Year 3 -# (TMY3) file for the -# location of Greensboro, North Carolina, from the pvlib data directory. This -# TMY3 file is constructed using the median month from each year between 1980 -# and 2003, from which we extract the first week of August 2001 to analyse. +# (TMY3) file for the location of Greensboro, North Carolina, from the pvlib +# data directory. This TMY3 file is constructed using the median month from +# each year between 1980 and 2003, from which we extract the first week of +# August 2001 to analyse. + # %% import pathlib from matplotlib import pyplot as plt @@ -62,10 +63,10 @@ # %% # First Solar # ----------- -# The First Solar function (:py:func:`pvlib.spectrum.spectral_factor_firstsolar -# `) -# for the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and -# the atmospheric precipitable water content, :math:`W`, as inputs. +# The First Solar function +# (:py:func:`pvlib.spectrum.spectral_factor_firstsolar`) for the spectral +# mismatch factor calculates :math:`M` using :math:`AM_a` and the atmospheric +# precipitable water content, :math:`W`, as inputs. # %% # Calculation of inputs @@ -106,7 +107,6 @@ # %% # Calculation of Spectral Mismatch # -------------------------------- - # Let's calculate the spectral mismatch factor using the three pvlib functions. # First, we need to import some model coefficients for the SAPM spectral factor # function, which, unlike the other two functions, lacks built-in coefficients. From 12c5d6cdcf578e622186c219987113d66dfc518a Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:18:31 +0100 Subject: [PATCH 06/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 42 +++++++++++------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index b9df47c9f1..3c9f5770f1 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -9,16 +9,16 @@ # Introduction # ------------ # This example demonstrates how to use different `spectrum.spectral_factor` -# models in pvlib to calculate the spectral mismatch factor, :math:`M`. While -# :math:`M` for a photovoltaic (PV) module can be calculated exactly using +# models in pvlib to calculate the spectral mismatch factor, M. While +# M for a photovoltaic (PV) module can be calculated exactly using # spectral irradiance and module spectral response data, these data are not # always available. pvlib provides several functions to estimate the spectral -# mismatch factor, :math:`M`, using proxies of the prevaiing spectral +# mismatch factor, M, using proxies of the prevaiing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. # More information on a range of spectral factor models, as well as the # variables upon which they are based, can be found in [1]_. - +# # Let's import some data. This example uses a Typical Meteorological Year 3 # (TMY3) file for the location of Greensboro, North Carolina, from the pvlib # data directory. This TMY3 file is constructed using the median month from @@ -38,7 +38,8 @@ meteo, metadata = pv.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', map_variables=True) meteo = meteo.sort_index() -meteo = meteo.between_time('06:00', '20:00').loc['2001-08-01':'2001-08-07'] +# meteo = meteo.between_time('06:00', '20:00').loc['2001-08-01':'2001-08-07'] +meteo = meteo.loc['2001-08-01':'2001-08-07'] # %% # pvlib Spectral Factor Functions @@ -48,24 +49,25 @@ # %% # SAPM -# ---- +# ^^^^ # The SAPM function (:py:func:`pvlib.spectrum.spectral_factor_sapm`) for the -# spectral mismatch factor calculates :math:`M` using absolute airmass, +# spectral mismatch factor calculates M using absolute airmass, # :math:`AM_a` as an input. # %% # PVSPEC +# ^^^^^^ # ------ # The PVSPEC function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) for -# the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and the +# the spectral mismatch factor calculates M using :math:`AM_a` and the # clearsky index, :math:`k_c` as inputs. # %% # First Solar -# ----------- +# ^^^^^^^^^^^ # The First Solar function # (:py:func:`pvlib.spectrum.spectral_factor_firstsolar`) for the spectral -# mismatch factor calculates :math:`M` using :math:`AM_a` and the atmospheric +# mismatch factor calculates M using :math:`AM_a` and the atmospheric # precipitable water content, :math:`W`, as inputs. # %% @@ -113,7 +115,7 @@ # Import some for a mc-Si module from the SAPM module database. module = pv.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] -# Calculate :math:`M` using the three models for an mc-Si PV module. +# Calculate M using the three models for an mc-Si PV module. m_sapm = pv.spectrum.spectral_factor_sapm(ama, module) m_pvspec = pv.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') m_fs = pv.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') @@ -126,33 +128,29 @@ # that this is not an exact comparison since the exact same PV modules has # not been modelled in each case, only the same module technology. -# Convert Dataframe Indexes to Month-Day our:Minute format -df_results.index = df_results.index.strftime("%m-%d") - -# Plot :math:`M` +# Plot M fig1, ax1 = plt.subplots() df_results.plot(ax=ax1) ax1.set_xlabel('Date (m-d H:M)') ax1.set_ylabel('Mismatch (-)') ax1.legend() +ax1.set_ylim(0.8, 1.2) plt.show() # We can also zoom in one one day, for example August 1st. -df_results.index = m_fs.index -df_results = df_results.loc['2001-08-01':'2001-08-01'] -df_results.index = df_results.index.strftime("%H:%M") fig2, ax1 = plt.subplots() -df_results.plot(ax=ax1) +df_results.loc['2001-08-01'].plot(ax=ax1) +ax1.set_ylim(0.8, 1.2) plt.show() # %% # References # ---------- -# .. [1] Daxini, Rajiv, and Yupeng Wu (2023). "Review of methods to account for -# the solar spectral influence on photovoltaic device performance." +# .. [1] Daxini, Rajiv, and Wu, Yupeng (2023). "Review of methods to account +# for the solar spectral influence on photovoltaic device performance." # Energy 286 -# :doi:`10.1364/AO.28.004735` +# :doi:`10.1016/j.energy.2023.129461` # .. [2] Kasten, F. and Young, A.T., 1989. Revised optical air mass tables # and approximation formula. Applied Optics, 28(22), pp.4735-4738. # :doi:`10.1364/AO.28.004735` From fedba9317db5464082cf8be07c1bfba66dbd1641 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:06:29 +0100 Subject: [PATCH 07/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 3c9f5770f1..8780bf5244 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -2,15 +2,15 @@ Spectral Mismatch Estimation ============================ Comparison of spectral factor calculation methods used to estimate the spectral -mismatch factor from atmopsheric variable inputs. +mismatch factor,:math:`M`, from atmopsheric variable inputs. """ # %% # Introduction # ------------ # This example demonstrates how to use different `spectrum.spectral_factor` -# models in pvlib to calculate the spectral mismatch factor, M. While -# M for a photovoltaic (PV) module can be calculated exactly using +# models in pvlib to calculate the spectral mismatch factor, :math:`M`. While +# :math:`M` for a photovoltaic (PV) module can be calculated exactly using # spectral irradiance and module spectral response data, these data are not # always available. pvlib provides several functions to estimate the spectral # mismatch factor, M, using proxies of the prevaiing spectral @@ -51,15 +51,14 @@ # SAPM # ^^^^ # The SAPM function (:py:func:`pvlib.spectrum.spectral_factor_sapm`) for the -# spectral mismatch factor calculates M using absolute airmass, +# spectral mismatch factor calculates :math:`M` using absolute airmass, # :math:`AM_a` as an input. # %% # PVSPEC # ^^^^^^ -# ------ # The PVSPEC function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) for -# the spectral mismatch factor calculates M using :math:`AM_a` and the +# the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and the # clearsky index, :math:`k_c` as inputs. # %% @@ -67,7 +66,7 @@ # ^^^^^^^^^^^ # The First Solar function # (:py:func:`pvlib.spectrum.spectral_factor_firstsolar`) for the spectral -# mismatch factor calculates M using :math:`AM_a` and the atmospheric +# mismatch factor calculates :math:`M` using :math:`AM_a` and the atmospheric # precipitable water content, :math:`W`, as inputs. # %% @@ -135,13 +134,13 @@ ax1.set_xlabel('Date (m-d H:M)') ax1.set_ylabel('Mismatch (-)') ax1.legend() -ax1.set_ylim(0.8, 1.2) +ax1.set_ylim(0.85, 1.15) plt.show() # We can also zoom in one one day, for example August 1st. fig2, ax1 = plt.subplots() df_results.loc['2001-08-01'].plot(ax=ax1) -ax1.set_ylim(0.8, 1.2) +ax1.set_ylim(0.85, 1.15) plt.show() # %% From eeea56b2dc10259c4dc2b43f6325e4c68ce5dfe7 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:13:38 +0100 Subject: [PATCH 08/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 8780bf5244..a1cdaadf51 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -2,7 +2,7 @@ Spectral Mismatch Estimation ============================ Comparison of spectral factor calculation methods used to estimate the spectral -mismatch factor,:math:`M`, from atmopsheric variable inputs. +mismatch factor, :math:`M`, from atmospheric variable inputs. """ # %% From bca1f937c238923f41b5ffdda9f8d56dad7a2b89 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:13:48 +0100 Subject: [PATCH 09/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index a1cdaadf51..7e69b24b8c 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -13,7 +13,7 @@ # :math:`M` for a photovoltaic (PV) module can be calculated exactly using # spectral irradiance and module spectral response data, these data are not # always available. pvlib provides several functions to estimate the spectral -# mismatch factor, M, using proxies of the prevaiing spectral +# mismatch factor, M, using proxies of the prevailing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. # More information on a range of spectral factor models, as well as the From 4c7ca2d05492f8006f9072b22cdd05a36b084227 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:58:01 +0100 Subject: [PATCH 10/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 31 ++++++----------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 7e69b24b8c..60525f55ee 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -45,29 +45,14 @@ # pvlib Spectral Factor Functions # ----------------------------- # This example demonstrates the application of three pvlib spectral factor -# functions, namely `SAPM`_, `PVSPEC`_, and `firstsolar`_. - -# %% -# SAPM -# ^^^^ -# The SAPM function (:py:func:`pvlib.spectrum.spectral_factor_sapm`) for the -# spectral mismatch factor calculates :math:`M` using absolute airmass, -# :math:`AM_a` as an input. - -# %% -# PVSPEC -# ^^^^^^ -# The PVSPEC function (:py:func:`pvlib.spectrum.spectral_factor_pvspec`) for -# the spectral mismatch factor calculates :math:`M` using :math:`AM_a` and the -# clearsky index, :math:`k_c` as inputs. - -# %% -# First Solar -# ^^^^^^^^^^^ -# The First Solar function -# (:py:func:`pvlib.spectrum.spectral_factor_firstsolar`) for the spectral -# mismatch factor calculates :math:`M` using :math:`AM_a` and the atmospheric -# precipitable water content, :math:`W`, as inputs. +# functions: +# +# - :py:func:`~pvlib.spectrum.spectral_factor_sapm`, which requires only +# the absolute airmass :math:`AM_a` +# - :py:func:`~pvlib.spectrum.spectral_factor_pvspec`, which requires +# :math:`AM_a` and the clearsky index :math:`k_c` +# - :py:func:`~pvlib.spectrum.spectral_factor_firstsolar`, which requires +# :math:`AM_a` and the atmospheric precipitable water content :math:`W` # %% # Calculation of inputs From 134fc3002a98acbc93084baa3b7231455721c682 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:58:19 +0100 Subject: [PATCH 11/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 60525f55ee..c067a9e875 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -86,7 +86,8 @@ kc = cs.ghi/meteo.ghi # :math:`W` is provided in the TMY3 file but in other cases can be calculated -# from temperature and relative humidity. +# from temperature and relative humidity +# (see :py:func:`pvlib.atmosphere.gueymard94_pw`). w = meteo.precipitable_water From 96c61447d5747e69988088e3bfafc8926def11fc Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:11:10 +0100 Subject: [PATCH 12/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index c067a9e875..019df9714d 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -36,9 +36,7 @@ DATA_DIR = pathlib.Path(pv.__file__).parent / 'data' meteo, metadata = pv.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', - map_variables=True) -meteo = meteo.sort_index() -# meteo = meteo.between_time('06:00', '20:00').loc['2001-08-01':'2001-08-07'] + coerce_year=2001, map_variables=True) meteo = meteo.loc['2001-08-01':'2001-08-07'] # %% From dba0ce85a33dccface29730c2d28faae44b3b900 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:12:05 +0100 Subject: [PATCH 13/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 019df9714d..19c323f924 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -107,7 +107,7 @@ # %% # Comparison Plots # ---------------- -# We can plot the results to visualisee variability between the models. Note +# We can plot the results to visualise variability between the models. Note # that this is not an exact comparison since the exact same PV modules has # not been modelled in each case, only the same module technology. From 2f1fa7a9c6c66b17f152349470d59ce5b3b561fe Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:16:35 +0100 Subject: [PATCH 14/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 19c323f924..519a0624a6 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -68,8 +68,8 @@ loc = location.Location(lat, lon, tz=tz, name='Greensboro, NC') # Calculate solar position parameters -solpos = get_solarposition( - meteo.index.shift(freq="-30min"), lat, lon, alt, +solpos = loc.get_solarposition( + meteo.index.shift(freq="-30min"), pressure=meteo.pressure*100, # convert from millibar to Pa temperature=meteo.temp_air) solpos.index = meteo.index # reset index to end of the hour From c3f9b05bcf7b8a64c6ec9e14038a624308a8aa9d Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:18:47 +0100 Subject: [PATCH 15/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 519a0624a6..4efe81a26c 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -31,7 +31,6 @@ import pandas as pd import pvlib as pv from pvlib import location -from pvlib.solarposition import get_solarposition from pvlib.atmosphere import get_relative_airmass DATA_DIR = pathlib.Path(pv.__file__).parent / 'data' From 9837013d44d965d25751f75f84602a469c4fafa3 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:27:25 +0100 Subject: [PATCH 16/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 4efe81a26c..8680202f9b 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -80,7 +80,7 @@ # the modelled clearky GHI. cs = loc.get_clearsky(meteo.index) -kc = cs.ghi/meteo.ghi +kc = pv.irradiance.clearsky_index(meteo.ghi, cs.ghi) # :math:`W` is provided in the TMY3 file but in other cases can be calculated # from temperature and relative humidity From 21043c9baddef4f4681645099472299aafcda152 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:22:19 +0100 Subject: [PATCH 17/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 8680202f9b..820d22b08f 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -29,13 +29,12 @@ import pathlib from matplotlib import pyplot as plt import pandas as pd -import pvlib as pv +import pvlib from pvlib import location -from pvlib.atmosphere import get_relative_airmass -DATA_DIR = pathlib.Path(pv.__file__).parent / 'data' -meteo, metadata = pv.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', - coerce_year=2001, map_variables=True) +DATA_DIR = pathlib.Path(pvlib.__file__).parent / 'data' +meteo, metadata = pvlib.iotools.read_tmy3(DATA_DIR / '723170TYA.CSV', + coerce_year=2001, map_variables=True) meteo = meteo.loc['2001-08-01':'2001-08-07'] # %% @@ -73,14 +72,15 @@ temperature=meteo.temp_air) solpos.index = meteo.index # reset index to end of the hour -amr = get_relative_airmass(solpos.apparent_zenith).dropna() # relative airmass +amr = pvlib.atmosphere.get_relative_airmass(solpos.apparent_zenith).dropna() +# relative airmass ama = amr*(meteo.pressure/1013.25) # absolute airmass # Now we calculate the clearsky index, :math:`kc`, by comparing the TMY3 GHI to # the modelled clearky GHI. cs = loc.get_clearsky(meteo.index) -kc = pv.irradiance.clearsky_index(meteo.ghi, cs.ghi) +kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) # :math:`W` is provided in the TMY3 file but in other cases can be calculated # from temperature and relative humidity @@ -96,11 +96,11 @@ # function, which, unlike the other two functions, lacks built-in coefficients. # Import some for a mc-Si module from the SAPM module database. -module = pv.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] +module = pvlib.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] # Calculate M using the three models for an mc-Si PV module. -m_sapm = pv.spectrum.spectral_factor_sapm(ama, module) -m_pvspec = pv.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') -m_fs = pv.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') +m_sapm = pvlib.spectrum.spectral_factor_sapm(ama, module) +m_pvspec = pvlib.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') +m_fs = pvlib.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') df_results = pd.concat([m_sapm, m_pvspec, m_fs], axis=1) df_results.columns = ['SAPM', 'PVSPEC', 'FS'] # %% @@ -122,7 +122,7 @@ # We can also zoom in one one day, for example August 1st. fig2, ax1 = plt.subplots() -df_results.loc['2001-08-01'].plot(ax=ax1) +df_results.loc['2001-08-02'].plot(ax=ax1) ax1.set_ylim(0.85, 1.15) plt.show() From 4254c85a5245c2c63a69d270f3a1969bd422608b Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:26:14 +0100 Subject: [PATCH 18/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Ioannis Sifnaios <88548539+IoannisSifnaios@users.noreply.github.com> --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 820d22b08f..eac79f3bf2 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -13,7 +13,7 @@ # :math:`M` for a photovoltaic (PV) module can be calculated exactly using # spectral irradiance and module spectral response data, these data are not # always available. pvlib provides several functions to estimate the spectral -# mismatch factor, M, using proxies of the prevailing spectral +# mismatch factor, :math:`M`, using proxies of the prevailing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. # More information on a range of spectral factor models, as well as the From 18ceb371f63d998a200de78049781dc0fbbc46b8 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:26:27 +0100 Subject: [PATCH 19/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Ioannis Sifnaios <88548539+IoannisSifnaios@users.noreply.github.com> --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index eac79f3bf2..44afd9057c 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -12,7 +12,7 @@ # models in pvlib to calculate the spectral mismatch factor, :math:`M`. While # :math:`M` for a photovoltaic (PV) module can be calculated exactly using # spectral irradiance and module spectral response data, these data are not -# always available. pvlib provides several functions to estimate the spectral +# always available. Pvlib provides several functions to estimate the spectral # mismatch factor, :math:`M`, using proxies of the prevailing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. From 1bf00b1d39fc8d2a99acc4bacf9d96e40beffd60 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:31:49 +0100 Subject: [PATCH 20/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 820d22b08f..c0bbfb3fc8 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -75,13 +75,13 @@ amr = pvlib.atmosphere.get_relative_airmass(solpos.apparent_zenith).dropna() # relative airmass ama = amr*(meteo.pressure/1013.25) # absolute airmass - +# %% # Now we calculate the clearsky index, :math:`kc`, by comparing the TMY3 GHI to # the modelled clearky GHI. cs = loc.get_clearsky(meteo.index) kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) - +# %% # :math:`W` is provided in the TMY3 file but in other cases can be calculated # from temperature and relative humidity # (see :py:func:`pvlib.atmosphere.gueymard94_pw`). From 8c859a7a175ffe2057d5ca282451b230a5cfd3c3 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:39:15 +0100 Subject: [PATCH 21/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 4ada83150e..083ce028c9 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -76,8 +76,8 @@ # relative airmass ama = amr*(meteo.pressure/1013.25) # absolute airmass # %% -# Now we calculate the clearsky index, :math:`kc`, by comparing the TMY3 GHI to -# the modelled clearky GHI. +# Now we calculate the clearsky index, :math:`k_c`, by comparing the TMY3 GHI +# to the modelled clearky GHI. cs = loc.get_clearsky(meteo.index) kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) From d935a7c933a607375d71f566d3858d16ddbdd0cb Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:15:05 +0100 Subject: [PATCH 22/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 083ce028c9..fe54e0d79c 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -111,7 +111,7 @@ # not been modelled in each case, only the same module technology. # Plot M -fig1, ax1 = plt.subplots() +fig1, ax1 = plt.subplots(figsize=(9.6, 7.2)) df_results.plot(ax=ax1) ax1.set_xlabel('Date (m-d H:M)') @@ -121,7 +121,7 @@ plt.show() # We can also zoom in one one day, for example August 1st. -fig2, ax1 = plt.subplots() +fig2, ax1 = plt.subplots(figsize=(9.6, 7.2)) df_results.loc['2001-08-02'].plot(ax=ax1) ax1.set_ylim(0.85, 1.15) plt.show() From 37bdee0fd6ee62afa897eedc8eab9e98c903b81b Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:38:47 +0100 Subject: [PATCH 23/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 37 ++++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index fe54e0d79c..bbe3ba211d 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -9,21 +9,21 @@ # Introduction # ------------ # This example demonstrates how to use different `spectrum.spectral_factor` -# models in pvlib to calculate the spectral mismatch factor, :math:`M`. While -# :math:`M` for a photovoltaic (PV) module can be calculated exactly using -# spectral irradiance and module spectral response data, these data are not -# always available. Pvlib provides several functions to estimate the spectral -# mismatch factor, :math:`M`, using proxies of the prevailing spectral +# models in pvlib-python to calculate the spectral mismatch factor, :math:`M`. +# While :math:`M` for a photovoltaic (PV) module can be calculated exactly +# using spectral irradiance and module spectral response data, these data are +# not always available. pvlib-python provides several functions to estimate the +# spectral mismatch factor, :math:`M`, using proxies of the prevailing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. # More information on a range of spectral factor models, as well as the # variables upon which they are based, can be found in [1]_. # # Let's import some data. This example uses a Typical Meteorological Year 3 -# (TMY3) file for the location of Greensboro, North Carolina, from the pvlib -# data directory. This TMY3 file is constructed using the median month from -# each year between 1980 and 2003, from which we extract the first week of -# August 2001 to analyse. +# (TMY3) file for the location of Greensboro, North Carolina, from the +# pvlib-python data directory. This TMY3 file is constructed using the median +# month from each year between 1980 and 2003, from which we extract the first +# week of August 2001 to analyse. # %% import pathlib @@ -38,10 +38,10 @@ meteo = meteo.loc['2001-08-01':'2001-08-07'] # %% -# pvlib Spectral Factor Functions -# ----------------------------- -# This example demonstrates the application of three pvlib spectral factor -# functions: +# Spectral Factor Functions +# ------------------------- +# This example demonstrates the application of three pvlib-python +# spectral factor functions: # # - :py:func:`~pvlib.spectrum.spectral_factor_sapm`, which requires only # the absolute airmass :math:`AM_a` @@ -91,9 +91,10 @@ # %% # Calculation of Spectral Mismatch # -------------------------------- -# Let's calculate the spectral mismatch factor using the three pvlib functions. -# First, we need to import some model coefficients for the SAPM spectral factor -# function, which, unlike the other two functions, lacks built-in coefficients. +# Let's calculate the spectral mismatch factor using the three spectral factor +# functions. First, we need to import some model coefficients for the SAPM +# spectral factor function, which, unlike the other two functions, lacks +# built-in coefficients. # Import some for a mc-Si module from the SAPM module database. module = pvlib.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] @@ -111,7 +112,7 @@ # not been modelled in each case, only the same module technology. # Plot M -fig1, ax1 = plt.subplots(figsize=(9.6, 7.2)) +fig1, ax1 = plt.subplots() df_results.plot(ax=ax1) ax1.set_xlabel('Date (m-d H:M)') @@ -121,7 +122,7 @@ plt.show() # We can also zoom in one one day, for example August 1st. -fig2, ax1 = plt.subplots(figsize=(9.6, 7.2)) +fig2, ax1 = plt.subplots() df_results.loc['2001-08-02'].plot(ax=ax1) ax1.set_ylim(0.85, 1.15) plt.show() From 665f494059d747ea7fb6cce85fc79d56f083a9fc Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:42:47 +0100 Subject: [PATCH 24/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index bbe3ba211d..79dafa0a25 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -120,7 +120,7 @@ ax1.legend() ax1.set_ylim(0.85, 1.15) plt.show() - +# %% # We can also zoom in one one day, for example August 1st. fig2, ax1 = plt.subplots() df_results.loc['2001-08-02'].plot(ax=ax1) From ea486840f424f51112dfe7e02494b850faa9fbcb Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:46:45 +0100 Subject: [PATCH 25/37] Update v0.11.1.rst --- docs/sphinx/source/whatsnew/v0.11.1.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.11.1.rst b/docs/sphinx/source/whatsnew/v0.11.1.rst index 1e839c596c..d29b62ef3f 100644 --- a/docs/sphinx/source/whatsnew/v0.11.1.rst +++ b/docs/sphinx/source/whatsnew/v0.11.1.rst @@ -25,6 +25,9 @@ Testing Documentation ~~~~~~~~~~~~~ +* Add new example to the example gallery to demonstrate the application of + several spectral mismatch factor models. + (:issue:`2107`, :pull:`2114`) Requirements @@ -34,3 +37,4 @@ Requirements Contributors ~~~~~~~~~~~~ * Echedey Luis (:ghuser:`echedey-ls`) +* Rajiv Daxini (:ghuser:`RDaxini`) From 3b0a79b125b91c04a84219466eeaa51c48fde59d Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:31:09 +0100 Subject: [PATCH 26/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 79dafa0a25..904cc8dd87 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -44,11 +44,11 @@ # spectral factor functions: # # - :py:func:`~pvlib.spectrum.spectral_factor_sapm`, which requires only -# the absolute airmass :math:`AM_a` +# the absolute airmass, :math:`AM_a` # - :py:func:`~pvlib.spectrum.spectral_factor_pvspec`, which requires -# :math:`AM_a` and the clearsky index :math:`k_c` +# :math:`AM_a` and the clearsky index, :math:`k_c` # - :py:func:`~pvlib.spectrum.spectral_factor_firstsolar`, which requires -# :math:`AM_a` and the atmospheric precipitable water content :math:`W` +# :math:`AM_a` and the atmospheric precipitable water content, :math:`W` # %% # Calculation of inputs @@ -120,11 +120,11 @@ ax1.legend() ax1.set_ylim(0.85, 1.15) plt.show() -# %% -# We can also zoom in one one day, for example August 1st. -fig2, ax1 = plt.subplots() -df_results.loc['2001-08-02'].plot(ax=ax1) -ax1.set_ylim(0.85, 1.15) + +# We can also zoom in one one day, for example August 2nd. +fig2, ax2 = plt.subplots() +df_results.loc['2001-08-02'].plot(ax=ax2) +ax2.set_ylim(0.85, 1.15) plt.show() # %% From d4c03cb03d6b0c879e6e34b837db8f9da49557ef Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:56:36 +0100 Subject: [PATCH 27/37] Update spectral_factor.py trying new plots (goal to increase size) --- docs/examples/spectrum/spectral_factor.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 904cc8dd87..acfed3c531 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -112,19 +112,21 @@ # not been modelled in each case, only the same module technology. # Plot M -fig1, ax1 = plt.subplots() -df_results.plot(ax=ax1) - -ax1.set_xlabel('Date (m-d H:M)') +fig1, (ax1, ax2) = plt.subplots(2, 1) +df_results.plot(ax=ax1, legend=False) +ax1.set_xlabel('Day') ax1.set_ylabel('Mismatch (-)') -ax1.legend() ax1.set_ylim(0.85, 1.15) -plt.show() # We can also zoom in one one day, for example August 2nd. -fig2, ax2 = plt.subplots() +# fig2, ax2 = plt.subplots() df_results.loc['2001-08-02'].plot(ax=ax2) +ax2.set_xlabel('Time') +ax2.set_ylabel('Mismatch (-)') ax2.set_ylim(0.85, 1.15) + +plt.tight_layout() + plt.show() # %% From 0af9b2d9e81b998aa8ddb73c14afe78b20a750de Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Thu, 4 Jul 2024 20:28:17 +0100 Subject: [PATCH 28/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index acfed3c531..63504b2584 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -77,7 +77,7 @@ ama = amr*(meteo.pressure/1013.25) # absolute airmass # %% # Now we calculate the clearsky index, :math:`k_c`, by comparing the TMY3 GHI -# to the modelled clearky GHI. +# to the modelled clearsky GHI. cs = loc.get_clearsky(meteo.index) kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) @@ -119,7 +119,6 @@ ax1.set_ylim(0.85, 1.15) # We can also zoom in one one day, for example August 2nd. -# fig2, ax2 = plt.subplots() df_results.loc['2001-08-02'].plot(ax=ax2) ax2.set_xlabel('Time') ax2.set_ylabel('Mismatch (-)') From e1398d3de4e8fd69a99b6a807cfde4a1c764c152 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:01:05 +0100 Subject: [PATCH 29/37] Apply suggestions from code review Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> Co-authored-by: Adam R. Jensen <39184289+AdamRJensen@users.noreply.github.com> --- docs/examples/spectrum/spectral_factor.py | 17 ++++++++++------- docs/sphinx/source/whatsnew/v0.11.1.rst | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 63504b2584..81072ddfe4 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -1,6 +1,7 @@ """ Spectral Mismatch Estimation ============================ + Comparison of spectral factor calculation methods used to estimate the spectral mismatch factor, :math:`M`, from atmospheric variable inputs. """ @@ -8,11 +9,11 @@ # %% # Introduction # ------------ -# This example demonstrates how to use different `spectrum.spectral_factor` +# This example demonstrates how to use different ``spectrum.spectral_factor_*`` # models in pvlib-python to calculate the spectral mismatch factor, :math:`M`. # While :math:`M` for a photovoltaic (PV) module can be calculated exactly # using spectral irradiance and module spectral response data, these data are -# not always available. pvlib-python provides several functions to estimate the +# often not available. pvlib-python provides several functions to estimate the # spectral mismatch factor, :math:`M`, using proxies of the prevailing spectral # irradiance conditions, such as air mass and clearsky index, which are easily # derived from common ground-based measurements such as broadband irradiance. @@ -76,8 +77,8 @@ # relative airmass ama = amr*(meteo.pressure/1013.25) # absolute airmass # %% -# Now we calculate the clearsky index, :math:`k_c`, by comparing the TMY3 GHI -# to the modelled clearsky GHI. +# Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI +# to clearsky GHI. cs = loc.get_clearsky(meteo.index) kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) @@ -98,10 +99,12 @@ # Import some for a mc-Si module from the SAPM module database. module = pvlib.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] +# # Calculate M using the three models for an mc-Si PV module. m_sapm = pvlib.spectrum.spectral_factor_sapm(ama, module) m_pvspec = pvlib.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') m_fs = pvlib.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') + df_results = pd.concat([m_sapm, m_pvspec, m_fs], axis=1) df_results.columns = ['SAPM', 'PVSPEC', 'FS'] # %% @@ -115,13 +118,13 @@ fig1, (ax1, ax2) = plt.subplots(2, 1) df_results.plot(ax=ax1, legend=False) ax1.set_xlabel('Day') -ax1.set_ylabel('Mismatch (-)') +ax1.set_ylabel('Spectral mismatch (-)') ax1.set_ylim(0.85, 1.15) # We can also zoom in one one day, for example August 2nd. df_results.loc['2001-08-02'].plot(ax=ax2) ax2.set_xlabel('Time') -ax2.set_ylabel('Mismatch (-)') +ax2.set_ylabel('Spectral mismatch (-)') ax2.set_ylim(0.85, 1.15) plt.tight_layout() @@ -131,7 +134,7 @@ # %% # References # ---------- -# .. [1] Daxini, Rajiv, and Wu, Yupeng (2023). "Review of methods to account +# .. [1] Daxini, R., and Wu, Y., 2023. "Review of methods to account # for the solar spectral influence on photovoltaic device performance." # Energy 286 # :doi:`10.1016/j.energy.2023.129461` diff --git a/docs/sphinx/source/whatsnew/v0.11.1.rst b/docs/sphinx/source/whatsnew/v0.11.1.rst index d29b62ef3f..a44ab96e36 100644 --- a/docs/sphinx/source/whatsnew/v0.11.1.rst +++ b/docs/sphinx/source/whatsnew/v0.11.1.rst @@ -25,7 +25,7 @@ Testing Documentation ~~~~~~~~~~~~~ -* Add new example to the example gallery to demonstrate the application of +* Added gallery example demonstrating the application of several spectral mismatch factor models. (:issue:`2107`, :pull:`2114`) From 69d9567a5a99cae62779c9243af4ae164c488908 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Sat, 6 Jul 2024 14:47:51 +0100 Subject: [PATCH 30/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 81072ddfe4..dabd30303e 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -2,8 +2,8 @@ Spectral Mismatch Estimation ============================ -Comparison of spectral factor calculation methods used to estimate the spectral -mismatch factor, :math:`M`, from atmospheric variable inputs. +Comparison of methods to estimate the spectral mismatch factor +from atmospheric variable inputs. """ # %% @@ -120,9 +120,11 @@ ax1.set_xlabel('Day') ax1.set_ylabel('Spectral mismatch (-)') ax1.set_ylim(0.85, 1.15) +ax1.legend(loc='upper center', frameon=False, ncols=3, + bbox_to_anchor=(0.5, 1.3)) # We can also zoom in one one day, for example August 2nd. -df_results.loc['2001-08-02'].plot(ax=ax2) +df_results.loc['2001-08-02'].plot(ax=ax2, legend=False) ax2.set_xlabel('Time') ax2.set_ylabel('Spectral mismatch (-)') ax2.set_ylim(0.85, 1.15) From 68edc03be2678a5041ccad3be34d0ff5294ab6bc Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:44:40 +0100 Subject: [PATCH 31/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Adam R. Jensen <39184289+AdamRJensen@users.noreply.github.com> --- docs/examples/spectrum/spectral_factor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index dabd30303e..2ecdae5112 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -20,7 +20,8 @@ # More information on a range of spectral factor models, as well as the # variables upon which they are based, can be found in [1]_. # -# Let's import some data. This example uses a Typical Meteorological Year 3 +# To demonstrate this functionality, first we need to import some data. +# This example uses a Typical Meteorological Year 3 # (TMY3) file for the location of Greensboro, North Carolina, from the # pvlib-python data directory. This TMY3 file is constructed using the median # month from each year between 1980 and 2003, from which we extract the first From 094a744dfa6c6a3720f2339f4a658685e1f57185 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:51:08 +0100 Subject: [PATCH 32/37] expand ama/amr initialism --- docs/examples/spectrum/spectral_factor.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 2ecdae5112..026484a971 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -74,9 +74,9 @@ temperature=meteo.temp_air) solpos.index = meteo.index # reset index to end of the hour -amr = pvlib.atmosphere.get_relative_airmass(solpos.apparent_zenith).dropna() -# relative airmass -ama = amr*(meteo.pressure/1013.25) # absolute airmass +airmass_relative = pvlib.atmosphere.get_relative_airmass( + solpos.apparent_zenith).dropna() +airmass_absolute = airmass_relative*(meteo.pressure/1013.25) # %% # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI # to clearsky GHI. @@ -102,9 +102,11 @@ module = pvlib.pvsystem.retrieve_sam('SandiaMod')['LG_LG290N1C_G3__2013_'] # # Calculate M using the three models for an mc-Si PV module. -m_sapm = pvlib.spectrum.spectral_factor_sapm(ama, module) -m_pvspec = pvlib.spectrum.spectral_factor_pvspec(ama, kc, 'multisi') -m_fs = pvlib.spectrum.spectral_factor_firstsolar(w, ama, 'multisi') +m_sapm = pvlib.spectrum.spectral_factor_sapm(airmass_absolute, module) +m_pvspec = pvlib.spectrum.spectral_factor_pvspec(airmass_absolute, kc, + 'multisi') +m_fs = pvlib.spectrum.spectral_factor_firstsolar(w, airmass_absolute, + 'multisi') df_results = pd.concat([m_sapm, m_pvspec, m_fs], axis=1) df_results.columns = ['SAPM', 'PVSPEC', 'FS'] From fa2e3533e9f4869351c78e22a3e78b9f59886a81 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:53:54 +0100 Subject: [PATCH 33/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 026484a971..89b43f8c03 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -75,7 +75,7 @@ solpos.index = meteo.index # reset index to end of the hour airmass_relative = pvlib.atmosphere.get_relative_airmass( - solpos.apparent_zenith).dropna() + solpos.apparent_zenith).dropna() airmass_absolute = airmass_relative*(meteo.pressure/1013.25) # %% # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI From 782e0762274cf0d3eff18368f09dab618cd829e1 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:11:06 +0100 Subject: [PATCH 34/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 89b43f8c03..f4266c6c6c 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -81,7 +81,8 @@ # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI # to clearsky GHI. -cs = loc.get_clearsky(meteo.index) +cs = loc.get_clearsky(meteo.index.shift(freq="-30min")) +cs.index = meteo.index # reset index to end of the hour kc = pvlib.irradiance.clearsky_index(meteo.ghi, cs.ghi) # %% # :math:`W` is provided in the TMY3 file but in other cases can be calculated From 19d6ddbf4031683fb41682636bf1c62813b3bf02 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 18:48:26 +0100 Subject: [PATCH 35/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index f4266c6c6c..8e37eb9bba 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -76,7 +76,7 @@ airmass_relative = pvlib.atmosphere.get_relative_airmass( solpos.apparent_zenith).dropna() -airmass_absolute = airmass_relative*(meteo.pressure/1013.25) +airmass_absolute = pvlib.atmosphere.get_absolute_airmass(airmass_relative) # %% # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI # to clearsky GHI. From 2db4db071b024749a4ada40de64747e1adf1fdde Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 19:57:59 +0100 Subject: [PATCH 36/37] Update docs/examples/spectrum/spectral_factor.py Co-authored-by: Kevin Anderson --- docs/examples/spectrum/spectral_factor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index 8e37eb9bba..f94df3a160 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -76,7 +76,7 @@ airmass_relative = pvlib.atmosphere.get_relative_airmass( solpos.apparent_zenith).dropna() -airmass_absolute = pvlib.atmosphere.get_absolute_airmass(airmass_relative) +airmass_absolute = pvlib.atmosphere.get_absolute_airmass(airmass_relative, pressure=meteo.pressure*100) # %% # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI # to clearsky GHI. From 63d52cb47352f04340dced84d1b5b3b3c01fc825 Mon Sep 17 00:00:00 2001 From: RDaxini <143435106+RDaxini@users.noreply.github.com> Date: Mon, 8 Jul 2024 20:01:44 +0100 Subject: [PATCH 37/37] Update spectral_factor.py --- docs/examples/spectrum/spectral_factor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples/spectrum/spectral_factor.py b/docs/examples/spectrum/spectral_factor.py index f94df3a160..83ee488fb4 100644 --- a/docs/examples/spectrum/spectral_factor.py +++ b/docs/examples/spectrum/spectral_factor.py @@ -76,7 +76,8 @@ airmass_relative = pvlib.atmosphere.get_relative_airmass( solpos.apparent_zenith).dropna() -airmass_absolute = pvlib.atmosphere.get_absolute_airmass(airmass_relative, pressure=meteo.pressure*100) +airmass_absolute = pvlib.atmosphere.get_absolute_airmass(airmass_relative, + meteo.pressure*100) # %% # Now we calculate the clearsky index, :math:`k_c`, which is the ratio of GHI # to clearsky GHI.