Project 1: Real-Time Earthquake Monitor

Build an interactive map that fetches live earthquake events, filters them, and renders a shareable HTML dashboard.


Quick Reference

Attribute Value
Difficulty Beginner
Time Estimate Weekend
Language Python (Alternatives: R, Julia)
Prerequisites Basic Python, JSON familiarity
Key Topics GeoJSON, spatial filters, time windows, web maps
Output HTML map + CLI summary

Learning Objectives

By completing this project, you will:

  1. Parse GeoJSON FeatureCollections and extract geometry and properties.
  2. Convert timestamps from epoch milliseconds to readable time.
  3. Filter events by magnitude, time range, and bounding box.
  4. Render an interactive map with styled markers and popups.
  5. Explain how coordinate order and projections affect map output.
  6. Package results as a static HTML artifact you can share.

The Core Question You’re Answering

“How do I turn a live GeoJSON feed into a map that people can explore and trust?”

This is the same question behind real disaster dashboards: the data is noisy, the format is strict, and the visualization must be precise enough that users can make decisions from it.


Concepts You Must Understand First

Concept Why It Matters Where to Learn
GeoJSON structure You must extract coordinates and properties correctly Python GIS intro (vector formats)
Coordinate order (lon, lat) Incorrect order puts markers in the wrong hemisphere GeoJSON spec + folium examples
Epoch timestamps USGS feeds use epoch ms, not human time Python datetime docs
Bounding boxes Fast spatial filtering without heavy geometry Any GIS basics guide
Web Mercator tiles Your map uses a projection even if you do not notice Map tiling docs

Key Concepts Deep Dive

  1. GeoJSON FeatureCollections
    • A FeatureCollection is a list of Features. Each Feature has geometry and properties.
    • For earthquakes, geometry is a Point and properties include magnitude, place, and time.
  2. Time Windows
    • The feed is a rolling window (past hour, day, week).
    • Your filters must convert epoch milliseconds to UTC and compare consistently.
  3. Bounding Box Filters
    • A bbox is [min_lon, min_lat, max_lon, max_lat].
    • Use bbox to reduce the dataset before rendering.
  4. Marker Styling
    • Magnitude is best shown with size and color.
    • Depth can be shown with color or tooltip text.

Theoretical Foundation

The Live Data Pipeline

┌────────────┐   ┌──────────────┐   ┌───────────────┐   ┌──────────────┐
│ USGS Feed  │ → │ GeoJSON Parse│ → │ Filter Events │ → │ Render Map   │
└────────────┘   └──────────────┘   └───────────────┘   └──────────────┘
       │                 │                 │                   │
       ▼                 ▼                 ▼                   ▼
  HTTP GET        Feature list       Reduced list         HTML output

GeoJSON Event Anatomy

A single earthquake feature looks like:

{
  "type": "Feature",
  "geometry": {"type": "Point", "coordinates": [-122.75, 38.78, 3.2]},
  "properties": {"mag": 2.5, "place": "5km NE of City", "time": 1704067200000}
}
  • coordinates: lon, lat, depth
  • properties.mag: magnitude for size/color
  • properties.time: epoch milliseconds

Why Projections Matter

Your markers are plotted on Web Mercator tiles. This is not a true-area projection, which means distances and areas are distorted at high latitudes. For a simple dashboard this is fine, but you must still respect coordinate order and scale carefully.


Project Specification

What You Will Build

A Python script that downloads the USGS GeoJSON feed, filters events, and writes a static HTML map with styled markers and popups.

Functional Requirements

  1. Fetch GeoJSON from a USGS endpoint.
  2. Filter by time window (hours back) and minimum magnitude.
  3. Optional bbox filter for region of interest.
  4. Render markers with size by magnitude and color by depth or magnitude.
  5. Save a standalone HTML file that opens in a browser.

Non-Functional Requirements

  • Resilience: Handle empty feeds or API errors.
  • Clarity: Popups show place, magnitude, time, and depth.
  • Configurability: CLI args or config for filters.

Example Usage / Output

$ python earthquake_map.py --min-mag 3.0 --hours 24 --bbox "-125,32,-114,42"
Fetched 812 events
Filtered to 23 events
Saved map to output/earthquakes.html

Real World Outcome

You open output/earthquakes.html and see:

  1. A map centered on your region.
  2. Circles sized by magnitude and colored by depth.
  3. Clicking a marker shows a popup with place, magnitude, and UTC time.
  4. A short legend or note indicating filter settings.

Solution Architecture

High-Level Design

USGS Feed
   |
   v
requests.get -> response.json
   |
   v
filter_events(events, min_mag, hours, bbox)
   |
   v
render_map(filtered_events) -> HTML

Key Components

Component Responsibility Key Decisions
Fetcher Download GeoJSON Endpoint selection and retries
Parser Extract fields Validate coordinate order
Filter Apply time and bbox Inclusive thresholds
Renderer Create map Folium marker style
Exporter Save output Output path naming

Data Structures

class Event:
    # lat, lon, depth, magnitude, time, place

Algorithm Overview

Event Filtering

  1. Convert event time from epoch ms to datetime.
  2. Skip events older than the time window.
  3. Skip events below minimum magnitude.
  4. If bbox is present, keep only points in bounds.

Complexity

  • Time: O(n) for n events.
  • Space: O(n) for filtered list.

Implementation Guide

Development Environment Setup

python -m venv geo-env
source geo-env/bin/activate
pip install requests folium

Project Structure

project-root/
├── src/
│   ├── earthquake_map.py
│   └── filters.py
├── output/
│   └── earthquakes.html
└── README.md

The Core Question You’re Answering

“How do I turn a raw GeoJSON feed into a trustworthy, usable map?”

Concepts You Must Understand First

  1. GeoJSON Fields
    • Know where magnitude, time, and coordinates live.
  2. Datetime Conversion
    • Epoch ms to UTC datetime.
  3. Spatial Filtering
    • Bbox filter logic and edge cases.

Questions to Guide Your Design

  1. What filters are most useful for users?
  2. How will you prevent marker clutter?
  3. What fields belong in popups vs tooltips?
  4. Should you log the filter counts for transparency?

Thinking Exercise

Take one feature from the feed and manually compute:

  • The latitude and longitude.
  • The human readable timestamp.
  • Whether it passes your filters.

Interview Questions

  1. What is GeoJSON and how is it structured?
  2. Why is coordinate order important?
  3. How do you filter points inside a bounding box?
  4. What projection do web maps use and why?
  5. How do you handle missing properties in live data?
  6. How would you cluster markers for dense regions?
  7. How do you make this usable offline?

Hints in Layers

  • Hint 1: Print one feature and map its fields.
  • Hint 2: Build a map with a single hard-coded marker.
  • Hint 3: Add filtering and track counts after each step.
  • Hint 4: Add marker clustering if the map slows down.

Books That Will Help

Topic Book Chapter
GeoJSON “Introduction to Python for Geographic Data Analysis” Vector data
Web maps Folium docs Quickstart
Time handling Python docs datetime

Implementation Phases

Phase 1: Fetch and Parse (2-3 hours)

  • Download GeoJSON
  • Inspect a sample feature
  • Extract event fields

Checkpoint: You can print a clean list of events.

Phase 2: Filtering and CLI (3-5 hours)

  • Add time and magnitude filters
  • Add bbox filters
  • Log filter counts

Checkpoint: You can reduce events to a region reliably.

Phase 3: Visualization (3-5 hours)

  • Render markers and popups
  • Add legend or note
  • Save HTML output

Checkpoint: Map is shareable and informative.

Key Implementation Decisions

Decision Options Recommendation Rationale
Map library Folium, Plotly, Leafmap Folium Simple HTML output
Filter interface CLI args, config CLI args Fast iteration
Marker style circle, icon circle Encodes magnitude easily

Testing Strategy

Test Categories

Category Purpose Examples
API fetch Data returned Non-empty feature list
Filter logic Correct counts Known small dataset
Output HTML saved File exists and opens

Critical Test Cases

  1. Empty feed or API error.
  2. Bbox that excludes all events.
  3. Events with missing properties.

Common Pitfalls and Debugging

Pitfall Symptom Solution
Lat/lon swapped Markers appear far away Always use lon, lat from GeoJSON
Wrong time unit No events Convert ms to seconds correctly
Too many markers Slow map Use clustering or filters

Extensions and Challenges

  • Add clustering and heatmap layers.
  • Add alerts for events within a radius of a point.
  • Add auto-refresh with a timestamp overlay.

Real-World Connections

  • Disaster dashboards and public alert systems.
  • News organizations mapping global earthquakes.
  • Emergency management spatial awareness tools.

Resources

  • USGS Earthquake API: https://earthquake.usgs.gov/fdsnws/event/1/
  • Folium docs: https://python-visualization.github.io/folium/
  • GeoJSON spec: https://geojson.org/

Self-Assessment Checklist

  • I can parse GeoJSON and explain its structure.
  • I can filter events by time and space.
  • I can render a map with meaningful styling.
  • I can explain how projections affect web maps.

Submission / Completion Criteria

Minimum Viable Completion

  • Fetch and render events on a map with at least one filter.

Full Completion

  • Time and magnitude filters, plus popups with details.

Excellence

  • Clustering, heatmaps, and alerting features.

This guide was generated from GEOSPATIAL_PYTHON_LEARNING_PROJECTS.md. For the complete learning path, see the parent directory GEOSPATIAL_PYTHON_LEARNING_PROJECTS/README.md.