From 0baa0498150a933990fcfb2f9e967ac909a8b11d Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sun, 8 Jun 2025 16:13:49 -0400 Subject: [PATCH 1/6] Rename solar position inputs in tracking.singleaxis --- .../plot_agrivoltaics_ground_irradiance.py | 4 +- .../shading/plot_martinez_shade_loss.py | 4 +- .../plot_single_axis_tracking.py | 8 ++-- ..._single_axis_tracking_on_sloped_terrain.py | 8 ++-- pvlib/tracking.py | 37 ++++++++++++------- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py b/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py index 094317589b..ca838b1022 100644 --- a/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py +++ b/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py @@ -58,8 +58,8 @@ # of the trackers. For a single-axis tracker, this can be calculated as: tracking_orientations = pvlib.tracking.singleaxis( - apparent_zenith=solpos['apparent_zenith'], - apparent_azimuth=solpos['azimuth'], + solar_zenith=solpos['apparent_zenith'], + solar_azimuth=solpos['azimuth'], axis_azimuth=axis_azimuth, max_angle=max_angle, backtrack=True, diff --git a/docs/examples/shading/plot_martinez_shade_loss.py b/docs/examples/shading/plot_martinez_shade_loss.py index 10ce77f741..82eaf429d7 100644 --- a/docs/examples/shading/plot_martinez_shade_loss.py +++ b/docs/examples/shading/plot_martinez_shade_loss.py @@ -89,8 +89,8 @@ ) # unpack for better readability tracking_result = pvlib.tracking.singleaxis( - apparent_zenith=solar_apparent_zenith, - apparent_azimuth=solar_azimuth, + solar_zenith=solar_apparent_zenith, + solar_azimuth=solar_azimuth, axis_tilt=axis_tilt, axis_azimuth=axis_azimuth, max_angle=(-90 + cross_axis_tilt, 90 + cross_axis_tilt), # (min, max) diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking.py b/docs/examples/solar-tracking/plot_single_axis_tracking.py index 80ed800be6..2c2da1d47a 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking.py @@ -32,8 +32,8 @@ solpos = solarposition.get_solarposition(times, lat, lon) truetracking_angles = tracking.singleaxis( - apparent_zenith=solpos['apparent_zenith'], - apparent_azimuth=solpos['azimuth'], + solar_zenith=solpos['apparent_zenith'], + solar_azimuth=solpos['azimuth'], axis_tilt=0, axis_azimuth=180, max_angle=90, @@ -60,8 +60,8 @@ for gcr in [0.2, 0.4, 0.6]: backtracking_angles = tracking.singleaxis( - apparent_zenith=solpos['apparent_zenith'], - apparent_azimuth=solpos['azimuth'], + solar_zenith=solpos['apparent_zenith'], + solar_azimuth=solpos['azimuth'], axis_tilt=0, axis_azimuth=180, max_angle=90, diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py index 979007efa1..4c784ceef0 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py @@ -99,8 +99,8 @@ fig, ax = plt.subplots() for cross_axis_tilt in [0, 5, 10]: tracker_data = tracking.singleaxis( - apparent_zenith=solpos['apparent_zenith'], - apparent_azimuth=solpos['azimuth'], + solar_zenith=solpos['apparent_zenith'], + solar_azimuth=solpos['azimuth'], axis_tilt=0, # flat because the axis is perpendicular to the slope axis_azimuth=180, # N-S axis, azimuth facing south max_angle=90, @@ -155,8 +155,8 @@ # before: tracker_data = tracking.singleaxis( - apparent_zenith=solpos['apparent_zenith'], - apparent_azimuth=solpos['azimuth'], + solar_zenith=solpos['apparent_zenith'], + solar_azimuth=solpos['azimuth'], axis_tilt=axis_tilt, # no longer flat because the terrain imparts a tilt axis_azimuth=axis_azimuth, max_angle=90, diff --git a/pvlib/tracking.py b/pvlib/tracking.py index afdaab2adf..ee475f8d51 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -4,9 +4,18 @@ from pvlib.tools import cosd, sind, tand, acosd, asind from pvlib import irradiance from pvlib import shading - - -def singleaxis(apparent_zenith, apparent_azimuth, +from pvlib._deprecation import renamed_kwarg_warning + + +@renamed_kwarg_warning( + since='0.13.1', + old_param_name='apparent_zenith', + new_param_name='solar_zenith') +@renamed_kwarg_warning( + since='0.13.1', + old_param_name='apparent_azimuth', + new_param_name='solar_azimuth') +def singleaxis(solar_zenith, solar_azimuth, axis_tilt=0, axis_azimuth=0, max_angle=90, backtrack=True, gcr=2.0/7.0, cross_axis_tilt=0): """ @@ -30,10 +39,10 @@ def singleaxis(apparent_zenith, apparent_azimuth, Parameters ---------- - apparent_zenith : float, 1d array, or Series + solar_zenith : float, 1d array, or Series Solar apparent zenith angles in decimal degrees. - apparent_azimuth : float, 1d array, or Series + solar_azimuth : float, 1d array, or Series Solar apparent azimuth angles in decimal degrees. axis_tilt : float, default 0 @@ -117,16 +126,16 @@ def singleaxis(apparent_zenith, apparent_azimuth, # MATLAB to Python conversion by # Will Holmgren (@wholmgren), U. Arizona. March, 2015. - if isinstance(apparent_zenith, pd.Series): - index = apparent_zenith.index + if isinstance(solar_zenith, pd.Series): + index = solar_zenith.index else: index = None # convert scalars to arrays - apparent_azimuth = np.atleast_1d(apparent_azimuth) - apparent_zenith = np.atleast_1d(apparent_zenith) + solar_azimuth = np.atleast_1d(solar_azimuth) + solar_zenith = np.atleast_1d(solar_zenith) - if apparent_azimuth.ndim > 1 or apparent_zenith.ndim > 1: + if solar_azimuth.ndim > 1 or solar_zenith.ndim > 1: raise ValueError('Input dimensions must not exceed 1') # The ideal tracking angle, omega_ideal, is the rotation to place the sun @@ -141,12 +150,12 @@ def singleaxis(apparent_zenith, apparent_azimuth, omega_ideal = shading.projected_solar_zenith_angle( axis_tilt=axis_tilt, axis_azimuth=axis_azimuth, - solar_zenith=apparent_zenith, - solar_azimuth=apparent_azimuth, + solar_zenith=solar_zenith, + solar_azimuth=solar_azimuth, ) # filter for sun above panel horizon - zen_gt_90 = apparent_zenith > 90 + zen_gt_90 = solar_zenith > 90 omega_ideal[zen_gt_90] = np.nan # Account for backtracking @@ -191,7 +200,7 @@ def singleaxis(apparent_zenith, apparent_azimuth, surface_tilt = surface['surface_tilt'] surface_azimuth = surface['surface_azimuth'] aoi = irradiance.aoi(surface_tilt, surface_azimuth, - apparent_zenith, apparent_azimuth) + solar_zenith, solar_azimuth) # Bundle DataFrame for return values and filter for sun below horizon. out = {'tracker_theta': tracker_theta, 'aoi': aoi, From 2a0fb08fc01ed47696ed5da84359f9ec5f050e12 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Sun, 8 Jun 2025 16:27:17 -0400 Subject: [PATCH 2/6] Update v0.13.1.rst --- docs/sphinx/source/whatsnew/v0.13.1.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/source/whatsnew/v0.13.1.rst b/docs/sphinx/source/whatsnew/v0.13.1.rst index 9a817f27bb..8bdcb59c03 100644 --- a/docs/sphinx/source/whatsnew/v0.13.1.rst +++ b/docs/sphinx/source/whatsnew/v0.13.1.rst @@ -10,7 +10,9 @@ Breaking Changes Deprecations ~~~~~~~~~~~~ - +* Rename parameter name ``aparent_zenith`` to ``solar_zenith`` and ``aparent_azimuth`` + to ``solar_azimuth`` in :py:func:`~pvlib.tracking.singleaxis`. + (:issue:`2479`, :pull:`2480`) Bug fixes ~~~~~~~~~ From 09c6fb2b1ae9c15a16669ec664518e2d019fa187 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:23:53 +0200 Subject: [PATCH 3/6] Revert solar_zenith to apparent_zenith --- .../plot_agrivoltaics_ground_irradiance.py | 2 +- .../shading/plot_martinez_shade_loss.py | 2 +- .../plot_single_axis_tracking.py | 4 ++-- ...t_single_axis_tracking_on_sloped_terrain.py | 4 ++-- docs/sphinx/source/whatsnew/v0.13.1.rst | 3 +-- pvlib/tracking.py | 18 +++++++----------- 6 files changed, 14 insertions(+), 19 deletions(-) diff --git a/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py b/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py index ca838b1022..521c68cb55 100644 --- a/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py +++ b/docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py @@ -58,7 +58,7 @@ # of the trackers. For a single-axis tracker, this can be calculated as: tracking_orientations = pvlib.tracking.singleaxis( - solar_zenith=solpos['apparent_zenith'], + apparent_zenith=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_azimuth=axis_azimuth, max_angle=max_angle, diff --git a/docs/examples/shading/plot_martinez_shade_loss.py b/docs/examples/shading/plot_martinez_shade_loss.py index 82eaf429d7..1ebf3a73b5 100644 --- a/docs/examples/shading/plot_martinez_shade_loss.py +++ b/docs/examples/shading/plot_martinez_shade_loss.py @@ -89,7 +89,7 @@ ) # unpack for better readability tracking_result = pvlib.tracking.singleaxis( - solar_zenith=solar_apparent_zenith, + apparent_zenith=solar_apparent_zenith, solar_azimuth=solar_azimuth, axis_tilt=axis_tilt, axis_azimuth=axis_azimuth, diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking.py b/docs/examples/solar-tracking/plot_single_axis_tracking.py index 2c2da1d47a..8487a5245c 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking.py @@ -32,7 +32,7 @@ solpos = solarposition.get_solarposition(times, lat, lon) truetracking_angles = tracking.singleaxis( - solar_zenith=solpos['apparent_zenith'], + apparent_zenith=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=0, axis_azimuth=180, @@ -60,7 +60,7 @@ for gcr in [0.2, 0.4, 0.6]: backtracking_angles = tracking.singleaxis( - solar_zenith=solpos['apparent_zenith'], + apparent=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=0, axis_azimuth=180, diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py index 4c784ceef0..fe25cb35c6 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py @@ -99,7 +99,7 @@ fig, ax = plt.subplots() for cross_axis_tilt in [0, 5, 10]: tracker_data = tracking.singleaxis( - solar_zenith=solpos['apparent_zenith'], + apparent=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=0, # flat because the axis is perpendicular to the slope axis_azimuth=180, # N-S axis, azimuth facing south @@ -155,7 +155,7 @@ # before: tracker_data = tracking.singleaxis( - solar_zenith=solpos['apparent_zenith'], + apparent=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=axis_tilt, # no longer flat because the terrain imparts a tilt axis_azimuth=axis_azimuth, diff --git a/docs/sphinx/source/whatsnew/v0.13.1.rst b/docs/sphinx/source/whatsnew/v0.13.1.rst index 8bdcb59c03..c242ce626c 100644 --- a/docs/sphinx/source/whatsnew/v0.13.1.rst +++ b/docs/sphinx/source/whatsnew/v0.13.1.rst @@ -10,8 +10,7 @@ Breaking Changes Deprecations ~~~~~~~~~~~~ -* Rename parameter name ``aparent_zenith`` to ``solar_zenith`` and ``aparent_azimuth`` - to ``solar_azimuth`` in :py:func:`~pvlib.tracking.singleaxis`. +* Rename parameter name ``aparent_azimuth`` to ``solar_azimuth`` in :py:func:`~pvlib.tracking.singleaxis`. (:issue:`2479`, :pull:`2480`) Bug fixes diff --git a/pvlib/tracking.py b/pvlib/tracking.py index ee475f8d51..f627614451 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -7,10 +7,6 @@ from pvlib._deprecation import renamed_kwarg_warning -@renamed_kwarg_warning( - since='0.13.1', - old_param_name='apparent_zenith', - new_param_name='solar_zenith') @renamed_kwarg_warning( since='0.13.1', old_param_name='apparent_azimuth', @@ -39,7 +35,7 @@ def singleaxis(solar_zenith, solar_azimuth, Parameters ---------- - solar_zenith : float, 1d array, or Series + apparent_zenith : float, 1d array, or Series Solar apparent zenith angles in decimal degrees. solar_azimuth : float, 1d array, or Series @@ -126,14 +122,14 @@ def singleaxis(solar_zenith, solar_azimuth, # MATLAB to Python conversion by # Will Holmgren (@wholmgren), U. Arizona. March, 2015. - if isinstance(solar_zenith, pd.Series): - index = solar_zenith.index + if isinstance(apparent_zenith, pd.Series): + index = apparent_zenith.index else: index = None # convert scalars to arrays solar_azimuth = np.atleast_1d(solar_azimuth) - solar_zenith = np.atleast_1d(solar_zenith) + apparent_zenith = np.atleast_1d(apparent_zenith) if solar_azimuth.ndim > 1 or solar_zenith.ndim > 1: raise ValueError('Input dimensions must not exceed 1') @@ -150,12 +146,12 @@ def singleaxis(solar_zenith, solar_azimuth, omega_ideal = shading.projected_solar_zenith_angle( axis_tilt=axis_tilt, axis_azimuth=axis_azimuth, - solar_zenith=solar_zenith, + solar_zenith=apparent_zenith, solar_azimuth=solar_azimuth, ) # filter for sun above panel horizon - zen_gt_90 = solar_zenith > 90 + zen_gt_90 = apparent_zenith > 90 omega_ideal[zen_gt_90] = np.nan # Account for backtracking @@ -200,7 +196,7 @@ def singleaxis(solar_zenith, solar_azimuth, surface_tilt = surface['surface_tilt'] surface_azimuth = surface['surface_azimuth'] aoi = irradiance.aoi(surface_tilt, surface_azimuth, - solar_zenith, solar_azimuth) + apparent_zenith, solar_azimuth) # Bundle DataFrame for return values and filter for sun below horizon. out = {'tracker_theta': tracker_theta, 'aoi': aoi, From 5c7c1e892cc8b2b70d8207294f1fd61138008b87 Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:31:42 +0200 Subject: [PATCH 4/6] One more fix --- pvlib/tracking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tracking.py b/pvlib/tracking.py index f627614451..7dfa9a567d 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -11,7 +11,7 @@ since='0.13.1', old_param_name='apparent_azimuth', new_param_name='solar_azimuth') -def singleaxis(solar_zenith, solar_azimuth, +def singleaxis(apparent_zenith, solar_azimuth, axis_tilt=0, axis_azimuth=0, max_angle=90, backtrack=True, gcr=2.0/7.0, cross_axis_tilt=0): """ From 6d200ffbe4abd944fdf10470c14b52732f54236c Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:34:46 +0200 Subject: [PATCH 5/6] One more more fix --- pvlib/tracking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tracking.py b/pvlib/tracking.py index 7dfa9a567d..ae50a5bc3f 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -131,7 +131,7 @@ def singleaxis(apparent_zenith, solar_azimuth, solar_azimuth = np.atleast_1d(solar_azimuth) apparent_zenith = np.atleast_1d(apparent_zenith) - if solar_azimuth.ndim > 1 or solar_zenith.ndim > 1: + if solar_azimuth.ndim > 1 or apparent_zenith.ndim > 1: raise ValueError('Input dimensions must not exceed 1') # The ideal tracking angle, omega_ideal, is the rotation to place the sun From f3d3f4ae27ab5fad67e8539cb6aa0afba292931c Mon Sep 17 00:00:00 2001 From: "Adam R. Jensen" <39184289+AdamRJensen@users.noreply.github.com> Date: Fri, 11 Jul 2025 12:34:29 +0200 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Kevin Anderson --- docs/examples/solar-tracking/plot_single_axis_tracking.py | 2 +- .../plot_single_axis_tracking_on_sloped_terrain.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking.py b/docs/examples/solar-tracking/plot_single_axis_tracking.py index 8487a5245c..4f7d62cb80 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking.py @@ -60,7 +60,7 @@ for gcr in [0.2, 0.4, 0.6]: backtracking_angles = tracking.singleaxis( - apparent=solpos['apparent_zenith'], + apparent_zenith=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=0, axis_azimuth=180, diff --git a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py index fe25cb35c6..b3a204ce69 100644 --- a/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py +++ b/docs/examples/solar-tracking/plot_single_axis_tracking_on_sloped_terrain.py @@ -99,7 +99,7 @@ fig, ax = plt.subplots() for cross_axis_tilt in [0, 5, 10]: tracker_data = tracking.singleaxis( - apparent=solpos['apparent_zenith'], + apparent_zenith=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=0, # flat because the axis is perpendicular to the slope axis_azimuth=180, # N-S axis, azimuth facing south @@ -155,7 +155,7 @@ # before: tracker_data = tracking.singleaxis( - apparent=solpos['apparent_zenith'], + apparent_zenith=solpos['apparent_zenith'], solar_azimuth=solpos['azimuth'], axis_tilt=axis_tilt, # no longer flat because the terrain imparts a tilt axis_azimuth=axis_azimuth,