File size: 5,640 Bytes
fcec389
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67d590e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2b3a5ca
 
 
 
 
 
 
 
 
 
fcec389
2b3a5ca
67d590e
 
fcec389
67d590e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcec389
67d590e
 
 
fcec389
67d590e
 
 
 
 
fcec389
67d590e
 
fcec389
67d590e
fcec389
 
 
 
 
 
 
 
0587a5f
fcec389
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import os
import streamlit as st
import pandas as pd
from geopy.geocoders import Nominatim
from streamlit_folium import st_folium
import folium
from datetime import datetime
import pytz
from timezonefinder import TimezoneFinder

from utils.satellite_utils import compute_ephemeris, fetch_custom_tle
from utils.timezone_utils import get_abbreviated_timezone

def main():
    st.title("Satellites Ephemeris Calculator")

    # Dropdown for satellite category selection
    satellite_categories = {
        'Starlink Generation 1': 'https://celestrak.org/NORAD/elements/supplemental/sup-gp.php?FILE=starlink&FORMAT=tle',
        'Starlink Generation 2': 'https://celestrak.org/NORAD/elements/supplemental/sup-gp.php?FILE=starlink&FORMAT=tle&VERSION=2',
        'OneWeb': 'https://celestrak.org/NORAD/elements/supplemental/sup-gp.php?FILE=oneweb&FORMAT=tle',
        'Kuiper': 'https://celestrak.org/NORAD/elements/supplemental/sup-gp.php?FILE=kuiper&FORMAT=tle',
        'Custom Satellite': None
    }
    satellite_type = st.selectbox("Select or Search Satellite", list(satellite_categories.keys()))

    custom_tle = None
    satellite_url = satellite_categories[satellite_type]

    # If custom satellite is selected, ask for satellite name or NORAD ID
    if satellite_type == 'Custom Satellite':
        satellite_name_or_id = st.text_input("Enter Satellite Name or NORAD ID:")
        if satellite_name_or_id:
            custom_tle = fetch_custom_tle(satellite_name_or_id)

    # Detect user's local time zone
    local_timezone = datetime.now().astimezone().tzinfo

    # Coordinates and time input - Default to mobile-friendly single-column layout
    use_address = st.checkbox("Use Address to Set Location", value=False)
    if use_address:
        address = st.text_input("Enter Your Address:")
        if address:
            geolocator = Nominatim(user_agent="satellite-observation-app")
            try:
                location = geolocator.geocode(address, timeout=10)
                if location:
                    latitude = location.latitude
                    longitude = location.longitude
                else:
                    st.write("Could not find the location. Please enter a valid address.")
            except Exception as e:
                st.error(f"Error fetching location data: {str(e)}")
    else:
        st.write("Select your location on the map:")
        # Use an empty container to manage the map rendering
        map_placeholder = st.empty()
        with map_placeholder:
            default_location = [37.7749, -122.4194]
            map_display = folium.Map(location=default_location, zoom_start=2)
            folium.Marker(default_location, tooltip="Default Location").add_to(map_display)
            map_data = st_folium(map_display, width=350, height=300)
            if map_data and 'last_clicked' in map_data and map_data['last_clicked']:
                latitude = map_data['last_clicked']['lat']
                longitude = map_data['last_clicked']['lng']

    # Latitude and Longitude input fields
    latitude = st.text_input("Latitude:", value=str(latitude) if 'latitude' in locals() else "")
    longitude = st.text_input("Longitude:", value=str(longitude) if 'longitude' in locals() else "")

    # Determine time zone from GPS coordinates
    if latitude and longitude:
        try:
            tf = TimezoneFinder()
            timezone_str = tf.timezone_at(lng=float(longitude), lat=float(latitude))
            timezone = pytz.timezone(timezone_str)
            current_time = datetime.now()
            timezone_abbr = get_abbreviated_timezone(timezone_str, current_time)
            st.write(f"Detected Time Zone: {timezone_str} ({timezone_abbr})")
        except Exception as e:
            st.error(f"Error determining timezone: {str(e)}")
            timezone = local_timezone
    else:
        timezone = local_timezone
        timezone_str = str(timezone)
        timezone_abbr = timezone.tzname(datetime.now())
        st.write(f"Using local time zone: {timezone} ({timezone_abbr})")

    start_date_local = st.date_input("Start Date (Local Time):")
    start_time_local = st.time_input("Start Time (Local Time):")
    end_time_local = st.time_input("End Time (Local Time):")

    # Convert local time to UTC
    start_datetime_local = datetime.combine(start_date_local, start_time_local)
    end_datetime_local = datetime.combine(start_date_local, end_time_local)
    start_datetime_utc = start_datetime_local.astimezone(pytz.utc)
    end_datetime_utc = end_datetime_local.astimezone(pytz.utc)

    st.write(f"Start Time in UTC: {start_datetime_utc.strftime('%Y-%m-%d %H:%M:%S')}")
    st.write(f"End Time in UTC: {end_datetime_utc.strftime('%Y-%m-%d %H:%M:%S')}")

    compute_button = st.button("Compute Satellite Positions")

    # Align the table with the button
    if compute_button:
        if latitude and longitude and start_date_local:
            ephemeris_df = compute_ephemeris(
                satellite_url, float(latitude), float(longitude),
                start_datetime_utc.strftime('%Y-%m-%d'),
                start_datetime_utc.time(), end_datetime_utc.time(),
                timezone_str,  # Pass the timezone string to the function
                custom_tle
            )
            if not ephemeris_df.empty:
                st.dataframe(ephemeris_df, use_container_width=True)
            else:
                st.write("No visible satellites found for the specified time and location.")
        else:
            st.write("Please fill in all fields (latitude, longitude, and observation time).")

if __name__ == "__main__":
    main()