Field of View Visualization Notebook

This Jupyter Notebook is meant to illustrate how the SatChecker FOV API (https://satchecker.cps.iau.org/fov) can be used with python/astropy to visualize satellite passes within a field of view.

[394]:
# FOV Visualization Notebook
# This Jupyter Notebook demonstrates how to visualize satellite positions
# from the SatChecker FOV API using astropy

import astropy.units as u
import matplotlib.pyplot as plt
import numpy as np
import requests
from astropy.coordinates import SkyCoord
from astropy.wcs import WCS

%matplotlib inline

[395]:
# Set up the FOV query parameters
mid_obs_time_jd = 2460584.519211  # Example JD
duration = 30  # seconds
ra_center = 224.048903  # Center RA in degrees
dec_center = 78.778084  # Center Dec in degrees
fov_radius = 5  # FOV radius in degrees
latitude = 43
longitude = -81
elevation = 300 # meters

# Make the API request
response = requests.get(
    f"https://dev.satchecker.cps.iau.noirlab.edu/fov/satellite-passes/?latitude={latitude}&longitude={longitude}&elevation={elevation}&mid_obs_time_jd={mid_obs_time_jd}&duration={duration}&ra={ra_center}&dec={dec_center}&fov_radius={fov_radius}&group_by=satellite",
    timeout=60
)
data = response.json()
[396]:
# Extract RA/Dec positions for each satellite
satellites = {}

for sat_key, sat_data in data['data']['satellites'].items():
    if sat_key not in satellites:
        satellites[sat_key] = []

    # Add ra, dec, and julian_date from each position
    for position in sat_data['positions']:
        satellites[sat_key].append([
            position['ra'],
            position['dec'],
            position['julian_date']
        ])

# Verify data
for sat in satellites:
    print(f"\n{sat}:")
    print(f"Number of points: {len(satellites[sat])}")

COSMOS 839 DEB (10439):
Number of points: 4

CZ-6A DEB (55190):
Number of points: 18

THOR ABLESTAR DEB (134):
Number of points: 30
[413]:
# Create a simple WCS
wcs = WCS(naxis=2)
wcs.wcs.crpix = [0, 0]
wcs.wcs.crval = [ra_center, dec_center]
wcs.wcs.cdelt = [0.1, 0.1]
wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']

# Create plot with WCS axes
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(1, 1, 1, projection=wcs)
center = SkyCoord(ra=ra_center*u.deg, dec=dec_center*u.deg, frame='icrs')

position_angles = np.linspace(0, 360, 360) * u.deg
circle_points = center.directional_offset_by(position_angles, fov_radius * u.deg)

# Plot the FOV circle
ax.plot(circle_points.ra.deg, circle_points.dec.deg,
        'b--', label='FOV', transform=ax.get_transform('world'))


# Plot coordinates
for sat_name in satellites.keys():
    ra = [pos[0] for pos in satellites[sat_name]]
    dec = [pos[1] for pos in satellites[sat_name]]



    coords = SkyCoord(ra=ra*u.deg, dec=dec*u.deg)
    # Satellite track
    ax.plot(coords.ra.deg, coords.dec.deg,
            transform=ax.get_transform('world'),
            label=sat_name)

    # Satellite position points
    ax.scatter(coords.ra.deg, coords.dec.deg,
               transform=ax.get_transform('world'), s=6)

    # Optional: Add start and end labels
    # Comment out if not needed
    times = [pos[2] for pos in satellites[sat_name]]
    if coords.ra.deg[0] < coords.ra.deg[-1]:
        ax.text(
            coords.ra.deg[0], coords.dec.deg[0], f'{sat_name} start',
            transform=ax.get_transform('world')
                )
        ax.text(
            coords.ra.deg[-1], coords.dec.deg[-1], f'{sat_name} end',
            transform=ax.get_transform('world')
        )
    else:
        ax.text(
            coords.ra.deg[0], coords.dec.deg[0], f'{sat_name} end',
            transform=ax.get_transform('world')
        )
        ax.text(
            coords.ra.deg[-1], coords.dec.deg[-1], f'{sat_name} start',
            transform=ax.get_transform('world')
        )


ax.set_aspect('equal')  # Force equal aspect ratio
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')

ax.set_xlabel('Right Ascension')
ax.set_ylabel('Declination')
ax.set_title(f'Satellite Passes in FOV ({fov_radius}°) at {mid_obs_time_jd}')
ax.grid(color='lightgray', linestyle='--')

plt.show()
../_images/notebooks_fov_4_0.png