|
import os |
|
import streamlit as st |
|
from skyfield.api import Topos, load, EarthSatellite |
|
import requests |
|
import pandas as pd |
|
import numpy as np |
|
from datetime import datetime |
|
import pytz |
|
|
|
def get_cardinal_direction(azimuth_degrees): |
|
""" |
|
Converts azimuth degrees to cardinal direction. |
|
""" |
|
directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'] |
|
index = int((azimuth_degrees + 22.5) // 45) |
|
return directions[index % 8] |
|
|
|
def compute_ephemeris(satellite_url, latitude, longitude, start_date_utc, start_time, end_time, timezone_str, custom_tle=None): |
|
""" |
|
Computes the ephemeris for the satellite and converts times to local time. |
|
""" |
|
try: |
|
ts = load.timescale() |
|
year, month, day = map(int, start_date_utc.split('-')) |
|
observer = Topos(latitude, longitude) |
|
start_hour, start_minute = start_time.hour, start_time.minute |
|
end_hour, end_minute = end_time.hour, end_time.minute |
|
start_datetime = datetime(year, month, day, start_hour, start_minute) |
|
end_datetime = datetime(year, month, day, end_hour, end_minute) |
|
total_minutes = int((end_datetime - start_datetime).total_seconds() // 60) |
|
times = ts.utc(year, month, day, [start_hour] * total_minutes, np.arange(start_minute, start_minute + total_minutes)) |
|
|
|
|
|
if custom_tle: |
|
satellites = [EarthSatellite(custom_tle[1], custom_tle[2], custom_tle[0], ts)] |
|
else: |
|
r = requests.get(satellite_url) |
|
with open('satellite_data.txt', 'wb') as f: |
|
f.write(r.content) |
|
satellites = load.tle_file('satellite_data.txt') |
|
|
|
|
|
ephemeris_data = [] |
|
local_tz = pytz.timezone(timezone_str) |
|
for satellite in satellites: |
|
difference = satellite - observer |
|
for ti in times: |
|
topocentric = difference.at(ti) |
|
ra, dec, distance = topocentric.radec() |
|
alt, az, distance = topocentric.altaz() |
|
|
|
if alt.degrees > 0: |
|
azimuth_degrees = az.degrees |
|
cardinal_direction = get_cardinal_direction(azimuth_degrees) |
|
|
|
|
|
local_time = ti.utc_datetime().replace(tzinfo=pytz.utc).astimezone(local_tz) |
|
|
|
ephemeris_data.append({ |
|
"Date (Local Time)": local_time.strftime('%Y-%m-%d %H:%M:%S'), |
|
"R.A.": str(ra), |
|
"Dec": str(dec), |
|
"Altitude": f"{alt.degrees:.2f}°", |
|
"Azimuth": f"{azimuth_degrees:.2f}° ({cardinal_direction})" |
|
}) |
|
|
|
|
|
ephemeris_df = pd.DataFrame(ephemeris_data) |
|
if not custom_tle: |
|
os.remove('satellite_data.txt') |
|
return ephemeris_df |
|
except Exception as e: |
|
st.error(f"Error computing ephemeris: {str(e)}") |
|
return pd.DataFrame() |
|
|
|
def fetch_custom_tle(satellite_name_or_id): |
|
""" |
|
Fetches TLE data for a custom satellite by name or NORAD ID. |
|
""" |
|
try: |
|
if satellite_name_or_id.isdigit(): |
|
celestrak_url = f'https://celestrak.org/NORAD/elements/gp.php?CATNR={satellite_name_or_id}' |
|
else: |
|
celestrak_url = f'https://celestrak.org/NORAD/elements/gp.php?NAME={satellite_name_or_id}&FORMAT=TLE' |
|
|
|
with st.spinner("Fetching TLE data..."): |
|
response = requests.get(celestrak_url) |
|
|
|
if response.status_code == 200 and len(response.text.splitlines()) >= 2: |
|
lines = response.text.splitlines() |
|
st.success("TLE data fetched successfully!") |
|
st.text(f"Name: {lines[0].strip()}\nTLE Line 1: {lines[1].strip()}\nTLE Line 2: {lines[2].strip()}") |
|
return lines[0].strip(), lines[1].strip(), lines[2].strip() |
|
else: |
|
st.error("TLE data could not be fetched. Please check the satellite name or NORAD ID.") |
|
return None |
|
except Exception as e: |
|
st.error(f"Error fetching TLE data: {str(e)}") |
|
return None |
|
|