Skip to content

olwal/air

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

204 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bay Area Air Quality: Interactive 4D Visualizations

3D visualization of air quality sensor data

This project visualizes air quality data overlaid onto a 3D geographical map. The map shows hourly data from thousands of sensors and allows interaction and playback of air quality pattern across various locations. These visualizations particularly highlight the significant impact that the 2020 Bay Area fires had on air quality, but can be used to explore patterns throughout the full year.

Tested platforms:

  • iOS (iPhone/iPad): Tested with Firefox, Chrome and Safari.
  • macOS/Windows: Tested with Firefox, Chrome and Safari.
  • Android: Tested with Firefox and Chrome. (clicking on city label not currently supported)

Use the menu to select a city, radius for the area to show sensors, and date range. Given the potential large amount of sensor data at a specific location/radius, the interface does not dynamically load new data as the map is panned. However, one can click a different city directly to load new data.

Interactive 3D demo (time-series sensor data)

sf_pan.mp4
sf_pan_2.mp4
▶ Pan SF → San Mateo · open demo ▶ Pan to SF · open demo

The application allows specification of location in California, start and end dates and other parameters for the visualization. (see URL parameters, below, for full list)

The animated 3D visualizations are based on sensor data from PurpleAir. The current viewer (in viewer/) is built with MapLibre GL JS for satellite imagery and 3D terrain, deck.gl for the GPU-rendered air-quality columns, and Vite as the build tool. Satellite imagery is switchable between seamless Sentinel-2 cloudless (default), high-resolution Esri World Imagery, and MapTiler, with automatic promotion to higher-resolution tiles when zoomed in. Data files were preprocessed with Python and Jupyter Lab.

The original 2020 version was built with procedural-gl.js and p5.js; it was rewritten onto MapLibre + deck.gl after procedural-gl.js became unmaintained. See viewer/README.md for how to run and build the current app.

Contents

2020 Bay Area fires

Here is a sample collection of interactive 3D visualization of air quality sensor data within a certain radius from the location, references to 3rd party material, and timelapse videos of the 3D visualizations. The visualizations are specified and configured through URL parameters.

LNU Lightning Complex Fires | Aug 17 to Oct 02

Interactive demo | Napa | Aug 16-Oct 03:

napa.mp4

▶ Open interactive demo — Napa

Interactive demo | Santa Cruz | Aug 16-Sep 23:

santa_cruz.mp4

▶ Open interactive demo — Santa Cruz

Interactive demo | Santa Clara | Aug 15-Oct 03:

santa_clara.mp4

▶ Open interactive demo — Santa Clara

2020 | 1-year Time Series

These full-year datasets take quite some time to load. Firefox on Desktop seems most stable in loading these.

3D views

sf_pan_to_320.mp4

Pan to San Francisco
sf_rotate_320.mp4

Rotating around San Francisco
east_bay_rotate_320.mp4

Rotating around East Bay
silicon_valley_approach_320.mp4

Approaching Silicon Valley

▶ Open the interactive demo

Input controls

Navigation

key command description
o ENTER orbit Start orbiting around location, click with mouse to stop
f focus Focus on specific location

Rendering

key command description
l labels Show/hide location labels
g graph Show/hide graph

Playback

key command description
p SPACE play/pause Start/stop playback
r rewind Rewind to beginning
x/X speed Increase/decrease playback speed
{ N < 10 back Step back 10 frames
[ n , 1 back Step back 1 frame
] m . 1 forward Step forward 1 frame
} M > 10 forward Step forward 10 frames

Interface

key command description
h help Show/hide instruction hint
ESC abort loading Abort loading data, useful when loading large datasets

Mouse motion

action description
Right button + move Rotate
Shift + Left button + move Rotate
Left button + move Pan
Center button + move Zoom
Scroll wheel Zoom
Click on location Load data for the location
Click on data point Focus on that data point

URL parameters

parameter description example default
location Bay area cities or one of the 3 lightning complex fires (see above). location=Santa Cruz
longitude Longitude for location. Not used if location parameter is specified. longitude=-122.08 -122.4194
latitude Latitude for location. Not used if location parameter is specified. latitude=37.4 37.7749
radius Radius (m) of area from the location to load sensor data for. radius=10000 7500
distance Canera distance distance=50000 20000
start_date YYYY-MM-DD for time series start. 2020-01-01 <= start_date <= 2021-01-01. start_date=2020-10-01 2020-08-19
end_date YYYY-MM-DD for time series end. 2020-01-01 <= end_date <= 2021-01-01. end_date=2020-11-25 2020-09-15

Examples:

description example
San Mateo, Sep 30-Oct 03 http://olwal.github.io/air/3d?location=San%20Mateo&start_date=2020-09-30&end_date=2020-10-03
Longitude/Latitude (Between Mountain View and Cupertino) with default dates http://olwal.github.io/air/3d?longitude=-122.08&latitude=37.35
Default location and dates, but 20 km radius http://olwal.github.io/air/3d?radius=20000
Alameda, Aug 15-Oct 03, 20 km radius, 30 km camera distance http://olwal.github.io/air/3d?location=Alameda&start_date=2020-08-15&end_date=2020-10-03&radius=20000&distance=30000

Running locally

The current app lives in viewer/ and is built with Vite:

cd viewer
npm install
npm run dev      # dev server at http://localhost:5173
npm run build    # production build -> viewer/dist/

The dev server serves the repo-root data/ directory automatically, so no data copying is needed. See viewer/README.md for imagery-source configuration, keyboard shortcuts, and the full URL-parameter reference.

Future work

Real-time sensor mode

The original 2020 version had an optional real-time mode (activated with a ?realtime=<seconds> URL parameter) that polled PurpleAir for each sensor's current reading and animated live air quality, instead of playing back the 2020 time series. It fetched per sensor from the public, keyless endpoint:

https://www.purpleair.com/json?show=<sensorId>

parsed PM2_5Value into an AQI, and refreshed on an interval. (See the legacy implementation in js/observations_remote.js.)

This no longer works. PurpleAir retired that endpoint — requests to it now redirect to an "over-quota" page and return no sensor data. The current viewer is therefore historical time-series only.

To restore real-time in the new viewer, the fetch layer would need to be rewritten against PurpleAir's current API at api.purpleair.com, which requires:

  • a registered read API key (the old endpoint needed none);
  • the v1 request shape — a single sensor (GET /v1/sensors/<id>?fields=pm2.5,...) or a bounded bulk query (GET /v1/sensors?fields=...&nwlng=...&selng=...) rather than one request per sensor;
  • mapping the new JSON response fields to the existing AQI/color pipeline in viewer/src/aqi.js;
  • keeping the API key out of the client — e.g. a small proxy/serverless function — and respecting PurpleAir's rate limits.

Acknowledgments

Many thanks to Oskar Rönnberg, Carsten Schwesig, and Sebastian Rinnebach for insightful feedback on the interface and features. Special thanks to Felix Palmer for discussions and for providing the open source procedural-gl.js library.

About

2D and 3D visualization of air quality sensor data.

Resources

Stars

11 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages