SURFACE_ORIENT
This function converts the rotation angle of a single-axis tracker into the conventional surface tilt and azimuth angles.
It accounts for the tilt and orientation of the tracker’s axis. This is useful for passing tracker geometry into standard transposition and irradiance models.
Excel Usage
=SURFACE_ORIENT(tracker_theta, axis_tilt, axis_azimuth)
tracker_theta(list[list], required): Tracker rotation angle (degrees).axis_tilt(float, optional, default: 0): Tilt of the rotation axis (degrees).axis_azimuth(float, optional, default: 0): Compass direction of the rotation axis (degrees).
Returns (list[list]): 2D list [[surface_tilt, surface_azimuth]], or an error string.
Example 1: 30 degree westward rotation on N-S axis
Inputs:
| tracker_theta | axis_tilt | axis_azimuth |
|---|---|---|
| 30 | 0 | 0 |
Excel formula:
=SURFACE_ORIENT({30}, 0, 0)
Expected output:
| Result | |
|---|---|
| 30 | 90 |
Example 2: 30 degree eastward rotation on N-S axis
Inputs:
| tracker_theta | axis_tilt | axis_azimuth |
|---|---|---|
| -30 | 0 | 0 |
Excel formula:
=SURFACE_ORIENT({-30}, 0, 0)
Expected output:
| Result | |
|---|---|
| 30 | 270 |
Example 3: Horizontal tracker orientation
Inputs:
| tracker_theta | axis_tilt | axis_azimuth |
|---|---|---|
| 0 | 0 | 180 |
Excel formula:
=SURFACE_ORIENT({0}, 0, 180)
Expected output:
| Result | |
|---|---|
| 0 | 270 |
Example 4: Vectorized tracker rotation inputs
Inputs:
| tracker_theta | axis_tilt | axis_azimuth | ||
|---|---|---|---|---|
| -20 | 0 | 20 | 0 | 180 |
Excel formula:
=SURFACE_ORIENT({-20,0,20}, 0, 180)
Expected output:
| Result | |
|---|---|
| 20 | 90 |
| 0 | 270 |
| 20 | 270 |
Python Code
Show Code
import pandas as pd
import numpy as np
from pvlib.tracking import calc_surface_orientation as result_func
def surface_orient(tracker_theta, axis_tilt=0, axis_azimuth=0):
"""
Calculate surface tilt and azimuth for a given tracker rotation.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.tracking.calc_surface_orientation.html
This example function is provided as-is without any representation of accuracy.
Args:
tracker_theta (list[list]): Tracker rotation angle (degrees).
axis_tilt (float, optional): Tilt of the rotation axis (degrees). Default is 0.
axis_azimuth (float, optional): Compass direction of the rotation axis (degrees). Default is 0.
Returns:
list[list]: 2D list [[surface_tilt, surface_azimuth]], or an error string.
"""
try:
def flatten_num(data):
if not isinstance(data, list): return [float(data)]
flat = []
for row in data:
row = row if isinstance(row, list) else [row]
for val in row:
if val == "": flat.append(float('nan'))
else: flat.append(float(val))
return flat
theta_list = flatten_num(tracker_theta)
if len(theta_list) == 0:
return "Error: tracker_theta cannot be empty"
at = float(axis_tilt) if axis_tilt is not None else 0.0
aa = float(axis_azimuth) if axis_azimuth is not None else 0.0
res = result_func(
tracker_theta=np.array(theta_list),
axis_tilt=at,
axis_azimuth=aa
)
# res is a DataFrame or OrderedDict
st = res['surface_tilt']
sa = res['surface_azimuth']
out = []
for i in range(len(theta_list)):
out.append([
float(st[i]) if not pd.isna(st[i]) else "",
float(sa[i]) if not pd.isna(sa[i]) else ""
])
return out
except Exception as e:
return f"Error: {str(e)}"Online Calculator
Tracker rotation angle (degrees).
Tilt of the rotation axis (degrees).
Compass direction of the rotation axis (degrees).