4.8 KiB
4.8 KiB
Simulador de Contaminació Marina
Visor web de trajectòries lagrangianes de ~10.000 partícules contaminants al Mediterrani occidental. Les partícules surten de punts de la costa catalana i es dispersen amb els corrents marins durant 72 hores. Quan arriben a la costa, s’encallen i s’acumulen, mostrant zones d’impacte.
Stack: Python · FastAPI · Next.js · Deck.gl · MapLibre (sense claus d’API)
Arquitectura
trajectories/
├── backend/ # API i dades
│ ├── main.py # FastAPI: metadata, blocs JSON/Arrow, CORS, gzip
│ ├── data/ # Dades servides per l’API
│ │ ├── metadata.json # (opcional) simulació "default" a la arrel
│ │ └── simulations/ # Una carpeta per simulació
│ │ └── <sim_id>/ # metadata.json, block_0.arrow, block_1.arrow, ...
│ ├── etl/ # Pipeline NetCDF → blocs Arrow + metadata
│ │ ├── nc_reader.py # Lectura NetCDF (lon, lat, u, v, beached, temps)
│ │ ├── pipeline.py # Orquestració: load_nc → subsample horari → write_blocks_arrow
│ │ └── to_blocks.py # Escriptura Arrow IPC + metadata.json
│ └── scripts/
│ └── run_etl.py # CLI: python -m scripts.run_etl fitxer.nc [--sim-id ...]
│
└── frontend/ # App Next.js (App Router)
├── src/
│ ├── app/page.tsx # Pàgina principal → TrajectoryMap
│ ├── components/ # MapView, MapHeader, TimePlayer, TrajectoryMap, IntroDialog, …
│ ├── hooks/ # useBlocks (càrrega Arrow/JSON), useSimulation, useMapLayers, useMetadata
│ ├── lib/ # constants, trajectoryData (buildTrails, buildTripsWithTime)
│ └── types/ # trajectory (Meta, Block, PointDatum, TripDatum, …)
- Backend: Servir
metadata.jsoni blocs de frames (JSON o Arrow IPC). Les dades viuen abackend/data/obackend/data/simulations/<sim_id>/. L’API accepta?sim=default(o qualsevolsim_id) per triar simulació. - Frontend: Demana metadata a
/api/metadata?sim=..., després els blocs a/api/block/{id}o/api/block/{id}/arrow. Construeix trails i trips a memòria (TripsLayer amb timestamps, PathLayer per selecció). Deck.gl + MapLibre renderitzen el mapa; el reproductor temporal avança elcurrentTimei es visualitzen les trajectòries amb color per origen, bloom/glow i partícules actives/beached.
Com arrencar el projecte
Requisits
- Backend: Python 3.10+, Node 18+ (només si no tens les dependències del backend instal·lades)
- Frontend: Node 18+
1. Backend
cd backend
# Entorn virtual i dependències
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
# Dades (una de les dues opcions)
# Opció A: Dades de prova (sense NetCDF)
python generate_dummy_data.py
# Opció B: ETL des d’un NetCDF (genera block_*.arrow + metadata a data/simulations/<sim_id>/)
python -m scripts.run_etl path/to/trajectories.nc
python -m scripts.run_etl path/to/file.nc --sim-id my_run --write-json # opcional JSON
# Servidor API (port 8000)
uvicorn main:app --reload
L’API queda disponible a http://localhost:8000.
2. Frontend
cd frontend
npm install
npm run dev
Obre http://localhost:3000. Per defecte el frontend crida l’API a http://localhost:8000 (configurable amb NEXT_PUBLIC_API_URL si cal).
3. Ús bàsic
- Backend en marxa (terminal 1), frontend en marxa (terminal 2).
- Obrir http://localhost:3000.
- Tancar/acceptar el popup d’introducció i esperar que carreguin els blocs (barra de progrés).
- Play / slider / velocitat (×0.5 … ×8). Zoom a les partícules (botó crosshair), Filters (basemap, capes), Info.
API (resum)
| Endpoint | Descripció |
|---|---|
GET /api/simulations |
Llista d’IDs de simulació disponibles |
GET /api/metadata?sim=default |
Metadata (num_particles, num_steps, num_blocks, seed_names, origins, time_start, time_end, …) |
GET /api/block/{id}?sim=default |
Bloc en JSON (frames + step_start, step_end, accumulation) |
GET /api/block/{id}/arrow?sim=default |
Bloc en Apache Arrow IPC (columnes: step, particle_id, lon, lat, u, v, beached) |
Característiques
- Partícules i temps: milers de partícules, 72 h (1 pas/hora), blocs de 24 h per càrrega progressiva.
- Trajectòries: TripsLayer amb cap arrodonit, color per origen (paleta), bloom/glow; partícules actives vs beached (vermell).
- Mapa: MapLibre (basemaps Carto), zoom/fit a partícules, tooltip amb origen i velocitat.
- Dades: ETL des de NetCDF (subsample horari, beached persistent) o dades de prova amb
generate_dummy_data.py.