diff --git a/app.py b/app.py index f87e16a..500c601 100644 --- a/app.py +++ b/app.py @@ -17,7 +17,7 @@ import streamlit as st st.set_page_config( page_title="Shannon's Equation for Dummies", - page_icon="๐Ÿ“ก", + page_icon="antenna_bars", layout="wide", initial_sidebar_state="expanded", ) @@ -104,7 +104,7 @@ st.markdown(""" # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with st.sidebar: - st.markdown("## ๐Ÿ“ก Shannon for Dummies") + st.markdown("## Shannon for Dummies") st.caption("Educational Application โ€” AP Feb 2021") st.divider() @@ -112,12 +112,12 @@ with st.sidebar: "Navigation", options=["animation", "orbits", "sat_types", "theory", "real_world", "contributions"], format_func=lambda x: { - "animation": "๐Ÿ“ก Satellite Link Animation", - "orbits": "๐ŸŒ GEO / MEO / LEO Orbits", - "sat_types": "๐Ÿ›ฐ๏ธ Satellite Missions & Types", - "theory": "๐Ÿงฎ Theoretical Exploration", - "real_world": "๐Ÿ›ฐ๏ธ Real World Link Budget", - "contributions": "๐Ÿ’ฌ Community Contributions", + "animation": "Satellite Link Animation", + "orbits": "GEO / MEO / LEO Orbits", + "sat_types": "Satellite Missions & Types", + "theory": "Theoretical Exploration", + "real_world": "Real World Link Budget", + "contributions": "Community Contributions", }[x], label_visibility="collapsed", ) diff --git a/core/help_texts.py b/core/help_texts.py index cf630b2..5143606 100644 --- a/core/help_texts.py +++ b/core/help_texts.py @@ -101,7 +101,7 @@ THEORY_HELP = { "- Try multiple values in all the fields one by one\n" "- Explore the graphs and try to understand the underlying physics\n" "- The units are as explicit as possible to facilitate the exploration\n" - "- Click on the โ„น๏ธ icons to get information about each parameter" + "- Click on the info icons to get information about each parameter" ), } @@ -134,7 +134,7 @@ REAL_WORLD_HELP = { "The position of the ground station affects link availability due to weather statistics " "(tropical regions have very heavy rains attenuating signals at high frequencies). " "It also impacts the elevation angle and overall path length.\n\n" - "๐Ÿ”— [Find coordinates](https://www.gps-coordinates.net)" + "[Find coordinates](https://www.gps-coordinates.net)" ), "availability": ( "**Link Availability [%]**\n\n" diff --git a/views/__pycache__/orbits_animation.cpython-313.pyc b/views/__pycache__/orbits_animation.cpython-313.pyc index c5f1459..b3a0a8c 100644 Binary files a/views/__pycache__/orbits_animation.cpython-313.pyc and b/views/__pycache__/orbits_animation.cpython-313.pyc differ diff --git a/views/__pycache__/satellite_types.cpython-313.pyc b/views/__pycache__/satellite_types.cpython-313.pyc index b6c18bb..354282a 100644 Binary files a/views/__pycache__/satellite_types.cpython-313.pyc and b/views/__pycache__/satellite_types.cpython-313.pyc differ diff --git a/views/contributions.py b/views/contributions.py index e6a40ab..f074d6a 100644 --- a/views/contributions.py +++ b/views/contributions.py @@ -11,17 +11,17 @@ from core.database import write_contribution, search_contributions, delete_contr def render(): """Render the Contributions page.""" - st.markdown("# ๐Ÿ’ฌ Community Contributions") + st.markdown("# Community Contributions") st.markdown( "Share your observations about Shannon's theorem, satellite communications, " "or suggest improvements. Contributions are stored locally and shared with all users." ) - tab_read, tab_write = st.tabs(["๐Ÿ“– Read Contributions", "โœ๏ธ Write Contribution"]) + tab_read, tab_write = st.tabs(["Read Contributions", "Write Contribution"]) # โ”€โ”€ Read Contributions โ”€โ”€ with tab_read: - st.markdown("### ๐Ÿ” Search Contributions") + st.markdown("### Search Contributions") db_choice = st.radio( "Database", @@ -39,7 +39,7 @@ def render(): kw_filter = st.text_input("Filter by Keywords", key="filter_kw") content_filter = st.text_input("Filter by Content", key="filter_content") - if st.button("๐Ÿ” Search", type="primary", key="btn_search"): + if st.button("Search", type="primary", key="btn_search"): results = search_contributions( db_name, name_filter=name_filter, @@ -60,10 +60,10 @@ def render(): ): st.markdown(contrib["text"]) if contrib["keywords"]: - st.caption(f"๐Ÿท๏ธ Keywords: {contrib['keywords']}") + st.caption(f"Keywords: {contrib['keywords']}") # Delete functionality - with st.popover("๐Ÿ—‘๏ธ Delete"): + with st.popover("Delete"): st.warning("This action cannot be undone.") del_password = st.text_input( "Enter contribution password", @@ -72,7 +72,7 @@ def render(): ) if st.button("Confirm Delete", key=f"del_btn_{contrib['num']}"): if delete_contribution(db_name, contrib["num"], del_password): - st.success(f"โœ… Contribution #{contrib['num']} deleted.") + st.success(f"Contribution #{contrib['num']} deleted.") # Refresh results st.session_state["contrib_results"] = search_contributions( db_name, @@ -83,13 +83,13 @@ def render(): ) st.rerun() else: - st.error("โŒ Incorrect password or contribution not found.") + st.error("Incorrect password or contribution not found.") elif "contrib_results" in st.session_state: st.info("No contributions found matching your filters.") # โ”€โ”€ Write Contribution โ”€โ”€ with tab_write: - st.markdown("### โœ๏ธ New Contribution") + st.markdown("### New Contribution") db_choice_w = st.radio( "Database", @@ -109,17 +109,16 @@ def render(): type="password", ) - submitted = st.form_submit_button("๐Ÿ“ค Submit", type="primary") + submitted = st.form_submit_button("Submit", type="primary") if submitted: if not name or not title or not text: - st.error("โŒ Please fill in all required fields (marked with *).") + st.error("Please fill in all required fields (marked with *).") else: new_id = write_contribution(db_name_w, name, title, keywords, text, password) - st.success(f"โœ… Thank you! Your contribution has been stored with ID #{new_id}.") - st.balloons() + st.success(f"Thank you. Your contribution has been stored with ID #{new_id}.") - with st.expander("โ“ Help"): + with st.expander("Help"): st.markdown( "Write your contribution as a free text. Contributions should be:\n\n" "- Candid observations about the technical subject\n" diff --git a/views/orbits_animation.py b/views/orbits_animation.py index b29a0f9..27a03f7 100644 --- a/views/orbits_animation.py +++ b/views/orbits_animation.py @@ -66,7 +66,7 @@ _ORBITS_HTML = """
-

๐Ÿ›ฐ๏ธ Orbit Comparison

+

Orbit Comparison

Hover over a satellite to see its details. @@ -226,8 +226,8 @@ function showInfo(o) {

FSPL${o.fsplDb}
Coverage${o.coverage}

-
โœ… Pros${o.pros}
-
โš ๏ธ Cons${o.cons}
+
Pros${o.pros}
+
Cons${o.cons}

Examples${o.examples}
`; @@ -489,7 +489,7 @@ draw(); def render(): """Render the GEO/MEO/LEO orbit comparison animation.""" - st.markdown("## ๐ŸŒ Satellite Orbits โ€” GEO vs MEO vs LEO") + st.markdown("## Satellite Orbits โ€” GEO vs MEO vs LEO") st.markdown( "Compare the three main satellite orbit types. " "Hover over satellites or legend items to explore their characteristics." @@ -500,50 +500,50 @@ def render(): # โ”€โ”€ Educational content below โ”€โ”€ st.divider() - st.markdown("### ๐Ÿ“Š Orbit Comparison at a Glance") + st.markdown("### Orbit Comparison at a Glance") col1, col2, col3 = st.columns(3) with col1: st.markdown(""" -#### ๐ŸŸข LEO โ€” Low Earth Orbit +#### LEO โ€” Low Earth Orbit **160 โ€“ 2 000 km** -- โšก Latency: **4 โ€“ 20 ms** (RTT) -- ๐Ÿ“‰ FSPL: ~155 dB (Ku-band) -- ๐Ÿ”„ Period: ~90 โ€“ 120 min -- ๐Ÿ“ก Small footprint โ†’ **large constellations** needed (hundreds to thousands) -- ๐Ÿค Requires **handover** between satellites -- ๐Ÿ›ฐ๏ธ *Starlink (550 km), OneWeb (1 200 km), Iridium (780 km)* +- Latency: **4 โ€“ 20 ms** (RTT) +- FSPL: ~155 dB (Ku-band) +- Period: ~90 โ€“ 120 min +- Small footprint โ†’ **large constellations** needed (hundreds to thousands) +- Requires **handover** between satellites +- *Starlink (550 km), OneWeb (1 200 km), Iridium (780 km)* """) with col2: st.markdown(""" -#### ๐ŸŸก MEO โ€” Medium Earth Orbit +#### MEO โ€” Medium Earth Orbit **2 000 โ€“ 35 786 km** -- โšก Latency: **40 โ€“ 80 ms** (RTT) -- ๐Ÿ“‰ FSPL: ~186 dB (Ku-band) -- ๐Ÿ”„ Period: ~2 โ€“ 12 h -- ๐Ÿ“ก Medium footprint โ†’ **medium constellations** (20 โ€“ 50 sats) -- ๐ŸŒ Good balance between coverage and latency -- ๐Ÿ›ฐ๏ธ *GPS (20 200 km), Galileo, O3b/SES (8 000 km)* +- Latency: **40 โ€“ 80 ms** (RTT) +- FSPL: ~186 dB (Ku-band) +- Period: ~2 โ€“ 12 h +- Medium footprint โ†’ **medium constellations** (20 โ€“ 50 sats) +- Good balance between coverage and latency +- *GPS (20 200 km), Galileo, O3b/SES (8 000 km)* """) with col3: st.markdown(""" -#### ๐Ÿ”ด GEO โ€” Geostationary Orbit +#### GEO โ€” Geostationary Orbit **35 786 km (fixed)** -- โšก Latency: **240 โ€“ 280 ms** (RTT) -- ๐Ÿ“‰ FSPL: ~205 dB (Ku-band) -- ๐Ÿ”„ Period: 23 h 56 min (= 1 sidereal day) -- ๐Ÿ“ก Huge footprint โ†’ **3 sats = global** coverage -- ๐Ÿ“Œ **Fixed position** in the sky โ€” no tracking needed -- ๐Ÿ›ฐ๏ธ *Intelsat, SES, Eutelsat, ViaSat* +- Latency: **240 โ€“ 280 ms** (RTT) +- FSPL: ~205 dB (Ku-band) +- Period: 23 h 56 min (= 1 sidereal day) +- Huge footprint โ†’ **3 sats = global** coverage +- **Fixed position** in the sky โ€” no tracking needed +- *Intelsat, SES, Eutelsat, ViaSat* """) - with st.expander("๐Ÿ”ฌ Key Trade-offs in Detail"): + with st.expander("Key Trade-offs in Detail"): st.markdown(r""" | Parameter | LEO | MEO | GEO | |:---|:---:|:---:|:---:| @@ -569,7 +569,7 @@ for the same bandwidth and transmit power. LEO compensates with lower FSPL but requires more satellites and complex handover. """) - with st.expander("๐Ÿ›ฐ๏ธ Notable Constellations"): + with st.expander("Notable Constellations"): st.markdown(""" | Constellation | Orbit | Altitude | # Satellites | Use Case | |:---|:---:|:---:|:---:|:---| diff --git a/views/real_world.py b/views/real_world.py index 52465d8..a6336b6 100644 --- a/views/real_world.py +++ b/views/real_world.py @@ -159,21 +159,21 @@ def render(): with col_img: st.image("Satellite.png", width=200) with col_title: - st.markdown("# ๐Ÿ›ฐ๏ธ Shannon & Friends in the Real World") + st.markdown("# Shannon & Friends in the Real World") st.markdown("From theory to satellite communication link budget.") wiki_cols = st.columns(4) - wiki_cols[0].link_button("๐Ÿ“– Harry Nyquist", "https://en.wikipedia.org/wiki/Harry_Nyquist") - wiki_cols[1].link_button("๐Ÿ“– Richard Hamming", "https://en.wikipedia.org/wiki/Richard_Hamming") - wiki_cols[2].link_button("๐Ÿ“– Andrew Viterbi", "https://en.wikipedia.org/wiki/Andrew_Viterbi") - wiki_cols[3].link_button("๐Ÿ“– Claude Berrou", "https://en.wikipedia.org/wiki/Claude_Berrou") + wiki_cols[0].link_button("Harry Nyquist", "https://en.wikipedia.org/wiki/Harry_Nyquist") + wiki_cols[1].link_button("Richard Hamming", "https://en.wikipedia.org/wiki/Richard_Hamming") + wiki_cols[2].link_button("Andrew Viterbi", "https://en.wikipedia.org/wiki/Andrew_Viterbi") + wiki_cols[3].link_button("Claude Berrou", "https://en.wikipedia.org/wiki/Claude_Berrou") st.divider() # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # SECTION 1: Satellite Link # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• - st.markdown("## ๐Ÿ“ก Satellite Link") + st.markdown("## Satellite Link") col1, col2, col3 = st.columns(3) with col1: @@ -213,7 +213,7 @@ def render(): try: sat_cir_list = [float(v.strip()) for v in sat_cir_input.split(",")] except ValueError: - st.error("โŒ Invalid C/I values.") + st.error("Invalid C/I values.") return # Compute satellite link @@ -224,11 +224,11 @@ def render(): sat_alt, sat_lat, sat_lon, gs_lat, gs_lon, availability, ) except Exception as e: - st.error(f"โŒ Satellite link computation error: {e}") + st.error(f"Satellite link computation error: {e}") return # Display satellite link results - st.markdown("#### ๐Ÿ“Š Satellite Link Results") + st.markdown("#### Satellite Link Results") r1, r2, r3 = st.columns(3) r1.metric("Output Power", fmt_power(sat["sig_power"]), help=REAL_WORLD_HELP["output_power"]) r2.metric("Antenna Gain", fmt_gain(sat["sat_gain_linear"]), help=REAL_WORLD_HELP["sat_gain"]) @@ -245,14 +245,14 @@ def render(): st.metric("Power Flux Density", fmt_pfd(sat["pfd_linear"]), help=REAL_WORLD_HELP["pfd"]) if sat["elevation"] <= 0: - st.warning("โš ๏ธ Satellite is below the horizon (negative elevation). Results may not be meaningful.") + st.warning("Satellite is below the horizon (negative elevation). Results may not be meaningful.") st.divider() # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # SECTION 2: Radio Front End # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• - st.markdown("## ๐Ÿ“ป Radio Front End") + st.markdown("## Radio Front End") col_r1, col_r2 = st.columns(2) with col_r1: @@ -268,10 +268,10 @@ def render(): cpe_ant_d, cpe_t_clear, ) except Exception as e: - st.error(f"โŒ Receiver computation error: {e}") + st.error(f"Receiver computation error: {e}") return - st.markdown("#### ๐Ÿ“Š Receiver Results") + st.markdown("#### Receiver Results") rx1, rx2 = st.columns(2) rx1.metric("Antenna Area ยท G/T", f"{rcv['cpe_ae']:.2f} mยฒ ยท {rcv['cpe_g_t']:.1f} dB/K", help=REAL_WORLD_HELP["cpe_gain"]) @@ -290,7 +290,7 @@ def render(): # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # SECTION 3: Baseband Unit # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• - st.markdown("## ๐Ÿ’ป Baseband Unit") + st.markdown("## Baseband Unit") col_b1, col_b2, col_b3 = st.columns(3) with col_b1: @@ -310,7 +310,7 @@ def render(): try: cnr_imp_list = [float(v.strip()) for v in cir_input.split(",")] except ValueError: - st.error("โŒ Invalid C/I values.") + st.error("Invalid C/I values.") return try: @@ -319,10 +319,10 @@ def render(): sat["sat_cir"], bandwidth, rolloff, overheads, cnr_imp_list, penalties, ) except Exception as e: - st.error(f"โŒ Baseband computation error: {e}") + st.error(f"Baseband computation error: {e}") return - st.markdown("#### ๐Ÿ“Š Baseband Results") + st.markdown("#### Baseband Results") b1, b2, b3 = st.columns(3) b1.metric("SNR in Available BW", f"{bb['cnr_bw']:.1f} dB in {bandwidth:.1f} MHz", @@ -336,7 +336,7 @@ def render(): b4, b5 = st.columns(2) with b4: - st.markdown("##### ๐ŸŽฏ Theoretical") + st.markdown("##### Theoretical") st.metric( "Theoretical BR", f"{fmt_br(bb['br_nyq'])} ยท {bb['br_nyq_norm']:.0%}", @@ -344,7 +344,7 @@ def render(): ) st.caption(f"Spectral Eff: {bb['spe_nyq']:.2f} bps/Hz ยท {bb['bits_per_symbol']:.2f} b/Symbol") with b5: - st.markdown("##### ๐Ÿญ Practical") + st.markdown("##### Practical") st.metric( "Physical Layer BR", f"{fmt_br(bb['br_rcv'])} ยท {bb['br_rcv_norm']:.0%}", @@ -360,12 +360,12 @@ def render(): st.divider() # โ”€โ”€ Graphs โ”€โ”€ - st.markdown("### ๐Ÿ“ˆ Interactive Graphs") + st.markdown("### Interactive Graphs") tab_bw, tab_pow, tab_map = st.tabs([ - "๐Ÿ“ถ BW Sensitivity", - "โšก Power Sensitivity", - "๐Ÿ—บ๏ธ BR Factor Map", + "BW Sensitivity", + "Power Sensitivity", + "BR Factor Map", ]) cnr_imp = combine_cnr(*cnr_imp_list) diff --git a/views/satellite_types.py b/views/satellite_types.py index 7cb3558..8806ab7 100644 --- a/views/satellite_types.py +++ b/views/satellite_types.py @@ -78,7 +78,7 @@ body{background:transparent;overflow:hidden;font-family:'Segoe UI',system-ui,san
-

๐Ÿ›ฐ๏ธ Satellite Missions

Select a mission type above
to explore its animation.

+

Satellite Missions

Select a mission type above
to explore its animation.

Mission Control โ€” choose a category