lucid-hf's picture
CI: deploy Docker/PDM Space
7735c3d verified
# pages/information.py
import streamlit as st
import pandas as pd
from pathlib import Path
import base64
import os
def _image_to_data_url(path: str) -> str:
p = Path(path)
if not p.is_absolute():
p = Path(__file__).parent / p
mime = "image/png" if p.suffix.lower() == ".png" else "image/jpeg"
b64 = base64.b64encode(p.read_bytes()).decode()
return f"data:{mime};base64,{b64}"
# Choose one of these:
# A) Env var: APP_ENV=prod on your server / cloud
APP_ENV = os.getenv("natsar", "local").lower()
# B) Or secrets: put env="prod" in .streamlit/secrets.toml on your server
# APP_ENV = st.secrets.get("env", "local").lower()
IS_LOCAL = True
# … later, where you currently render your Deploy controls …
if IS_LOCAL:
st.markdown("""
<style>
/* Hide the toolbar and header (which creates the black bar) */
[data-testid="stToolbar"] { display: none !important; }
header[data-testid="stHeader"] { display: none !important; }
/* (Legacy fallbacks) */
#MainMenu { visibility: hidden; }
footer { visibility: hidden; }
/* Remove the empty space the header leaves behind */
[data-testid="stAppViewContainer"] { padding-top: 0 !important; }
[data-testid="stAppViewContainer"] .main .block-container { padding-top: 0 !important; }
/* Give the sidebar a little breathing room at the top */
section[data-testid="stSidebar"] > div:first-child { padding-top: 0.5rem; }
</style>
""", unsafe_allow_html=True)
# =============== Page setup ===============
st.markdown("""
<style>
.block-container { padding-top: 1.2rem; padding-bottom: 0.6rem; max-width: 1400px; }
h2, h3, h4 { margin: 0.4rem 0; }
textarea { min-height: 70px !important; }
/* Light outline on inputs */
.stSelectbox > div, .stTextInput > div, .stNumberInput > div, .stDateInput > div, .stTextArea > div {
border: 1px solid #D0D0D0; border-radius: 6px;
}
</style>
""", unsafe_allow_html=True)
st.set_page_config(
page_title="Information – Time-Critical Survival Markers",
layout="wide",
initial_sidebar_state="expanded",
)
# =============== Header ===============
st.markdown(
"<h2 style='text-align:center;margin-top:0;font-size:4.0em;color:yellow'>SAR-X<sup>ai</h2>"
"<h2 style='text-align:center;margin-top:0'>Survival Information ℹ️</h2>"
"<p style='text-align:center;opacity:0.8'>Time-critical survival markers for a person lost in the bush (temperate conditions)</p>",
unsafe_allow_html=True,
)
# =============== Sidebar navigation ===============
with st.sidebar:
logo_data_url = _image_to_data_url("../resources/images/lucid_insights_logo.png")
st.markdown(
f"""
<div style="text-align:left; margin: 0 0 0.8rem 0.25rem;">
<img src="{logo_data_url}" alt="Lucid Insights" style="width:160px; height:auto; margin-bottom:0.5rem;">
</div>
""",
unsafe_allow_html=True,
)
st.markdown("---")
st.page_link("app.py", label="Home")
#st.page_link("pages/lost_at_sea.py", label="Lost at Sea")
st.page_link("pages/signal_watch.py", label="Signal Watch")
st.page_link("pages/bushland_beacon.py", label="Bushland Beacon")
st.page_link("pages/misc_find.py", label="Misc Finder")
st.markdown("---")
st.page_link("pages/task_satellite.py", label="Task Satellite")
st.page_link("pages/task_drone.py", label="Task Drone")
st.page_link("pages/information.py", label="Survival Information")
st.markdown("---")
st.caption("Note: This page provides general SAR heuristics, not medical advice.")
# =============== Intro callouts ===============
st.info(
"These guidelines summarise **time-critical survival markers** and how SAR priorities shift over time."
)
st.warning(
"Assumptions: adult subject, temperate Australian bushland, unknown preparedness. "
"Heat, cold, rain, injuries, age, fitness, and comorbidities can change timelines significantly."
)
# =============== Sections ===============
with st.expander("πŸŒ… Golden First 24 Hours (0–24 hours) β€” highest chance of rescue", expanded=False):
st.markdown(
"""
- **Hydration:** Dehydration commonly begins after **8–12 h** without water (faster if hot or moving). Early cognitive effects can appear within **4–6 h** in heat.
- **Exposure:** Inland/elevation nights can drop quickly. **Hypothermia risk** emerges after **6–8 h** if wet, still, or poorly clothed.
- **Navigation decisions:** First **6–12 h** often see β€œpanic travel” that increases distance from the last known point (LKP).
- **Search priority:** Confirm **LKP**, direction of travel, and behaviour profile. Emphasise **2–5 km radius**; rapid hasty search with air/ground visual.
"""
)
with st.expander("🌀 Critical Window: 24–72 Hours (1–3 days) β€” rapidly declining odds"):
st.markdown(
"""
- **Water:** Typical survival **2–3 days** in mild conditions; **<24 h** possible in high heat without water.
- **Exposure:** **Hyperthermia/hypothermia** overtakes food as primary risk.
- **Food:** Generally **not critical** yet; energy loss slows mobility and decision-making.
- **Injuries:** Uncontrolled bleeding, fractures, or infection become life-threatening within **48–72 h**.
- **Search priority:** Expand to **5–15 km**; focus **terrain traps** (gullies, creeks, shelter). Deploy **IR/thermal** and **dogs** before scent degrades (**~48 h**).
"""
)
with st.expander("πŸŒ‘ Extended Phase: 3–7 Days β€” survival depends on shelter/water"):
st.markdown(
"""
- **Hydration:** Without access to water, fatal dehydration is likely by **Day 3–4**.
- **Exposure:** Repeated night/day stress without shelter becomes fatal.
- **Psychological:** Disorientation, apathy, and β€œcurl-up syndrome” can appear by **Day 3–5**.
- **Search priority:** If no indicators, some agencies start transitioning from rescue to recovery by **Day 5–7**. Prioritise creeks, shade, and downhill drift lines.
"""
)
with st.expander("πŸ• Beyond 7 Days β€” survival requires water and some bushcraft"):
st.markdown(
"""
- **Physiology:** Untrained adult **without water** rarely survives beyond **~4 days**. **With water**, **7–10 days** can be possible.
- **Exceptions:** Documented survivals of **10–14 days** exist where water and shelter were available and the subject stayed put.
- **Search tactics:** Mostly recovery, but **stationary heat signatures** and drainages remain key.
"""
)
with st.expander("🚨 Practical SAR Implications β€” time-based tasking"):
st.markdown(
"""
- **0–6 h:** Immediate **hasty search** around LKP; phone pings; visual scans.
- **6–24 h:** **Air assets/drones with thermal**, **dogs** while scent is strong.
- **24–48 h:** Retask to **watercourses/shelter zones**; anticipate a **stationary subject**.
- **48 h+:** Scale sectors, sustainment mode; factor **psychological fatigue** and immobility.
"""
)
# =============== Markers Table ===============
st.markdown("### 🧭 Key SAR Survival Indicators (time-critical markers)")
markers_df = pd.DataFrame(
[
("Dehydration", "8–24 h", "Major cognitive & mobility decline"),
("Hypothermia (wet/cold night)", "4–8 h", "Potentially fatal overnight"),
("Hyperthermia (hot day)", "2–6 h", "Rapid collapse β‰₯ ~35 Β°C"),
("Injury infection", "24–48 h", "Sepsis risk increases rapidly"),
("Scent decay (tracking dogs)", "36–48 h", "Sharp reduction in success"),
("Signal flares / phone battery", "12–36 h", "Most devices flat within a day"),
("Water depletion", "48–72 h", "Common fatal threshold"),
("Food depletion", "5–10 d", "Secondary vs water/exposure"),
],
columns=["Marker", "Typical Onset", "Survival Risk"],
)
st.dataframe(
markers_df,
use_container_width=True,
hide_index=True,
)
# =============== Optional illustrative chart ===============
st.markdown("### πŸ“ˆ Survival timeline (illustrative)")
st.caption(
"A simple heuristic visual showing relative risk accumulation over time. "
"Not a prediction model; use alongside weather, terrain, subject profile, and intel."
)
show_chart = st.toggle("Show illustrative risk timeline", value=False)
if show_chart:
import numpy as np
import matplotlib.pyplot as plt
# Hours 0–168 (7 days)
hours = np.arange(0, 169)
# Heuristic relative risk curves (0–100) for visualisation purposes only
# Faster rise for hyperthermia (hot day), early rise for hypothermia at night, steady climb for dehydration
dehydration = np.clip((hours / 72) ** 1.2 * 100, 0, 100) # steeper after ~72h
hypothermia = np.clip(np.piecewise(
hours,
[hours < 8, (hours >= 8) & (hours < 24), hours >= 24],
[lambda h: (h/8) * 50, lambda h: 50 + (h-8) * (30/16), lambda h: 80 + (h-24) * (20/144)]
), 0, 100)
hyperthermia = np.clip(np.piecewise(
hours,
[hours < 6, hours >= 6],
[lambda h: (h/6) * 70, lambda h: 70 + (h-6) * (30/162)]
), 0, 100)
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(hours, dehydration, label="Dehydration (no water)")
ax.plot(hours, hypothermia, label="Hypothermia (wet/cold night)")
ax.plot(hours, hyperthermia, label="Hyperthermia (hot day)")
ax.set_xlabel("Hours since lost")
ax.set_ylabel("Relative risk (0–100)")
ax.set_title("Illustrative risk accumulation over time")
ax.grid(True, alpha=0.3)
ax.legend(loc="upper left")
st.pyplot(fig)
# =============== Footer note ===============
st.caption(
"Β© SAR-Xai β€” This page summarises common SAR timelines to aid triage and tasking. "
"Always adapt to local conditions, intel, and policy."
)