{"id":"v001","input":{"lat":39.74,"lon":-104.99,"time":"2026-06-21T13:00-06:00","camera_pitch":"-90 deg"},"expect":{"result.hotspot_angle.value":16.30250602122443,"result.sun_elevation.value":73.69749397877557,"result.sun_azimuth.value":178.49048707854078,"result.in_frame":"yes","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id":"v002","input":{"lat":39.74,"lon":-104.99,"time":"2026-06-21T09:00-06:00","camera_pitch":"-90 deg"},"expect":{"result.hotspot_angle.value":52.95100054682075,"result.sun_elevation.value":37.04899945317925,"result.sun_azimuth.value":88.80854908835796,"result.in_frame":"no","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id":"v003","input":{"lat":51.48,"lon":-0.0,"time":"2026-03-20T12:10Z","camera_pitch":"-60 deg","camera_heading":"0 deg","field_of_view":"84 deg"},"expect":{"result.hotspot_angle.value":21.50941866026404,"result.sun_elevation.value":38.496851050332424,"result.sun_azimuth.value":180.82041814472683,"result.in_frame":"yes","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id":"v004","input":{"lat":-33.87,"lon":151.21,"time":"2026-12-21T12:00+11:00","camera_pitch":"-45 deg","camera_heading":"180 deg","field_of_view":"70 deg"},"expect":{"result.hotspot_angle.value":36.918704510788096,"result.sun_elevation.value":74.40691421637098,"result.sun_azimuth.value":51.46773202852475,"result.in_frame":"no","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id":"v005","input":{"lat":35.0,"lon":-110.0,"time":"2026-09-22T17:30-07:00","camera_pitch":"-10 deg","camera_heading":"270 deg","field_of_view":"60 deg"},"expect":{"result.hotspot_angle.value":160.23140061419588,"result.sun_elevation.value":8.795447080108756,"result.sun_azimuth.value":263.8458741052807,"result.in_frame":"no","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id":"v006","input":{"lat":60.0,"lon":10.0,"time":"2026-06-21T02:00Z","camera_pitch":"-90 deg"},"expect":{"result.hotspot_angle.value":89.95958869286385,"result.sun_elevation.value":0.040411307136147934,"result.sun_azimuth.value":35.76369076411598,"result.in_frame":"no","ok":true},"source":"NOAA solar equations (tools/vectors/gen_sun.py) and vector geometry (tools/vectors/gen_hotspot.py)","sourceVersion":"NOAA GML 2023","tolerance":{"result.hotspot_angle.value":{"abs":0.02},"result.sun_elevation.value":{"abs":0.02},"result.sun_azimuth.value":{"abs":0.02}}}
{"id": "v007", "input": {"lat": 39.74, "lon": -104.99, "time": "2026-06-21T15:00:00-06:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 29.751695252318395, "result.sun_elevation.value": 60.24830474768161, "result.sun_azimuth.value": 245.67066286699756, "result.antisolar_azimuth.value": 65.67066286699753, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v008", "input": {"lat": 39.74, "lon": -104.99, "time": "2026-06-21T07:30:00-06:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 70.0246019913176, "result.sun_elevation.value": 19.9753980086824, "result.sun_azimuth.value": 75.59706848399992, "result.antisolar_azimuth.value": 255.59706848399992, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v009", "input": {"lat": 39.74, "lon": -104.99, "time": "2026-12-21T12:00:00-07:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 63.14805075874108, "result.sun_elevation.value": 26.851949241258918, "result.sun_azimuth.value": 180.47062865150835, "result.antisolar_azimuth.value": 0.4706286515083775, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v010", "input": {"lat": 39.74, "lon": -104.99, "time": "2026-06-21T12:00:00-06:00", "camera_pitch": "-60 deg", "camera_heading": "0 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 20.14134912847132, "result.sun_elevation.value": 69.11634619578388, "result.sun_azimuth.value": 136.6990495760155, "result.antisolar_azimuth.value": 316.6990495760155, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v011", "input": {"lat": 39.74, "lon": -104.99, "time": "2026-06-21T12:00:00-06:00", "camera_pitch": "-60 deg", "camera_heading": "180 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 47.201676635945695, "result.sun_elevation.value": 69.11634619578388, "result.sun_azimuth.value": 136.6990495760155, "result.antisolar_azimuth.value": 316.6990495760155, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v012", "input": {"lat": 51.48, "lon": -0.12, "time": "2026-05-15T13:00:00+01:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 32.53971254277001, "result.sun_elevation.value": 57.46028745722999, "result.sun_azimuth.value": 181.39906569125205, "result.antisolar_azimuth.value": 1.3990656912520762, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v013", "input": {"lat": 51.48, "lon": -0.12, "time": "2026-05-15T13:00:00+01:00", "camera_pitch": "-45 deg", "camera_heading": "90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 52.743038157556065, "result.sun_elevation.value": 57.46028745722999, "result.sun_azimuth.value": 181.39906569125205, "result.antisolar_azimuth.value": 1.3990656912520762, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v014", "input": {"lat": -33.87, "lon": 151.21, "time": "2026-01-15T13:00:00+11:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 12.758560705775459, "result.sun_elevation.value": 77.24143929422453, "result.sun_azimuth.value": 4.655031656161782, "result.antisolar_azimuth.value": 184.65503165616178, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v015", "input": {"lat": -33.87, "lon": 151.21, "time": "2026-07-15T12:00:00+10:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 55.3866720764453, "result.sun_elevation.value": 34.613327923554706, "result.sun_azimuth.value": 0.3192057697067412, "result.antisolar_azimuth.value": 180.31920576970674, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v016", "input": {"lat": 1.35, "lon": 103.82, "time": "2026-03-21T13:00:00+08:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 3.1872261468746763, "result.sun_elevation.value": 86.81277385312534, "result.sun_azimuth.value": 110.45417765092742, "result.antisolar_azimuth.value": 290.4541776509274, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v017", "input": {"lat": 1.35, "lon": 103.82, "time": "2026-03-21T08:00:00+08:00", "camera_pitch": "-30 deg", "camera_heading": "270 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 17.929026955333626, "result.sun_elevation.value": 12.071386691774658, "result.sun_azimuth.value": 90.13126252108412, "result.antisolar_azimuth.value": 270.1312625210841, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v018", "input": {"lat": 64.13, "lon": -21.9, "time": "2026-06-21T12:00:00+00:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 43.25519820982375, "result.sun_elevation.value": 46.74480179017625, "result.sun_azimuth.value": 149.39605069311358, "result.antisolar_azimuth.value": 329.3960506931136, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v019", "input": {"lat": 64.13, "lon": -21.9, "time": "2026-06-21T23:00:00+00:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 87.4598491722763, "result.sun_elevation.value": 2.5401508277237133, "result.sun_azimuth.value": 326.12071411450825, "result.antisolar_azimuth.value": 146.12071411450825, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v020", "input": {"lat": -22.91, "lon": -43.17, "time": "2026-09-18T12:00:00-03:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 24.81336793732964, "result.sun_elevation.value": 65.18663206267037, "result.sun_azimuth.value": 352.11147849837783, "result.antisolar_azimuth.value": 172.1114784983779, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v021", "input": {"lat": 35.68, "lon": 139.69, "time": "2026-04-10T10:00:00+09:00", "camera_pitch": "-70 deg", "camera_heading": "45 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 41.22855812113831, "result.sun_elevation.value": 53.64837689304688, "result.sun_azimuth.value": 133.66114485581755, "result.antisolar_azimuth.value": 313.66114485581755, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v022", "input": {"lat": 47.62, "lon": -122.35, "time": "2026-08-05T17:00:00-07:00", "camera_pitch": "-90 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 55.06570298279229, "result.sun_elevation.value": 34.93429701720772, "result.sun_azimuth.value": 255.90615318927982, "result.antisolar_azimuth.value": 75.90615318927985, "result.in_frame": "no"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
{"id": "v023", "input": {"lat": 25.2, "lon": 55.27, "time": "2026-11-11T09:30:00+04:00", "camera_pitch": "-55 deg", "camera_heading": "315 deg"}, "expect": {"ok": true, "result.hotspot_angle.value": 21.562792429330337, "result.sun_elevation.value": 33.43721041943177, "result.sun_azimuth.value": 134.9841678818858, "result.antisolar_azimuth.value": 314.9841678818858, "result.in_frame": "yes"}, "source": "Sun position from pvlib's NREL SPA (sea level, 101325 Pa, 12 C); antisolar point and hotspot angle by vector geometry (tools/vectors/gen_sun_pvlib.py)", "sourceVersion": "pvlib 0.13.0", "tolerance": {"result.hotspot_angle.value": {"abs": 0.003}, "result.sun_elevation.value": {"abs": 0.003}, "result.sun_azimuth.value": {"abs": 0.003}, "result.antisolar_azimuth.value": {"abs": 0.003}, "result.in_frame": {"abs": 0}}}
