File size: 5,017 Bytes
448e634 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 25ac52c ff71114 25ac52c ff71114 25ac52c ff71114 25ac52c ff71114 25ac52c ff71114 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 b359d50 ff71114 25ac52c ff71114 b47d08c ff71114 b47d08c ff71114 b359d50 ff71114 |
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 124 125 126 127 128 129 130 131 |
import streamlit as st
import pandas as pd
import plotly.express as px
from datetime import date, timedelta
# Import ObsPy for live data fetching
import obspy
from obspy.clients.fdsn import Client
from obspy import UTCDateTime
# --- Page Configuration ---
st.set_page_config(
page_title="Live Earthquake Explorer (ObsPy)",
page_icon="π°οΈ",
layout="wide",
initial_sidebar_state="expanded"
)
# --- Live Data Fetching Function using ObsPy ---
@st.cache_data(ttl=900) # Cache the data for 15 minutes
def fetch_live_data(start_date, end_date, min_mag):
"""
Fetches live earthquake data from the IRIS FDSN web service using ObsPy.
"""
client = Client("IRIS")
start_time = UTCDateTime(start_date)
end_time = UTCDateTime(end_date) + timedelta(days=1)
try:
catalog = client.get_events(
starttime=start_time,
endtime=end_time,
minmagnitude=min_mag
)
except Exception as e:
st.error(f"Could not retrieve data from IRIS FDSN service: {e}")
return pd.DataFrame()
event_list = []
for event in catalog:
if not (event.preferred_origin() and event.preferred_magnitude()):
continue
origin = event.preferred_origin()
magnitude = event.preferred_magnitude()
# Get location description safely.
description = "N/A"
if hasattr(event, 'descriptions'):
if event.descriptions and event.descriptions[0].text:
description = event.descriptions[0].text
event_list.append({
"latitude": origin.latitude,
"longitude": origin.longitude,
"depth": origin.depth / 1000,
"magnitude": magnitude.mag,
"time": origin.time.datetime,
"place": description,
})
if not event_list:
return pd.DataFrame()
return pd.DataFrame(event_list)
# --- UI Design ---
st.title("π°οΈ Live Earthquake Explorer with ObsPy")
st.markdown("Data is fetched in real-time from the **IRIS FDSN** web service.")
with st.sidebar:
st.header("π Search Parameters")
today = date.today()
thirty_days_ago = today - timedelta(days=30)
start_date = st.date_input("Start Date", value=thirty_days_ago)
end_date = st.date_input("End Date", value=today)
min_magnitude = st.slider("Minimum Magnitude", 0.0, 10.0, 5.0, 0.1)
search_button = st.button("Search Earthquakes", type="primary", use_container_width=True)
# --- Main Content Area ---
if search_button:
if start_date > end_date:
st.error("Error: Start date cannot be after end date.")
else:
with st.spinner(f"Fetching earthquakes from {start_date} to {end_date}..."):
df = fetch_live_data(start_date, end_date, min_magnitude)
if not df.empty:
st.success(f"Found {len(df)} earthquakes matching your criteria.")
st.subheader("π Summary Statistics")
col1, col2, col3 = st.columns(3)
col1.metric("Total Earthquakes", f"{len(df):,}")
col2.metric("Largest Magnitude", f"{df['magnitude'].max():.1f}")
col3.metric("Deepest Event (km)", f"{df['depth'].max():.1f}")
st.markdown("---")
st.subheader("π Interactive Earthquake Map")
st.markdown("Hover over points for details. Circle size represents magnitude.")
fig = px.scatter_geo(
df,
lat='latitude',
lon='longitude',
size='magnitude',
color='depth',
hover_name='place',
hover_data={'latitude': ':.2f', 'longitude': ':.2f', 'time': '|%Y-%m-%d %H:%M', 'magnitude': ':.1f', 'depth': ':.1f km'},
projection="natural earth",
title=f"Live Earthquakes from {start_date} to {end_date} (Magnitude > {min_magnitude})",
color_continuous_scale=px.colors.sequential.Plasma_r
)
fig.update_layout(margin={"r":0,"t":40,"l":0,"b":0}, coloraxis_colorbar_title_text='Depth (km)')
st.plotly_chart(fig, use_container_width=True)
# --- Show Earthquakes in a Table ---
st.subheader("π Detailed Earthquake Data")
# This line is changed to show latitude and longitude instead of place.
display_df = df[['time', 'latitude', 'longitude', 'magnitude', 'depth']].copy()
st.dataframe(
display_df.sort_values(by='time', ascending=False),
use_container_width=True,
height=400,
column_config={"time": st.column_config.DatetimeColumn("Time (UTC)", format="YYYY-MM-DD HH:mm")}
)
else:
st.warning("No earthquakes were found for the specified criteria. Try expanding the date range or lowering the magnitude.")
else:
st.info("Set your desired parameters in the sidebar and click 'Search Earthquakes' to begin.") |