2026-05-04 09:44:56 +02:00

108 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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, sencallen i sacumulen, mostrant zones dimpacte.
**Stack:** Python · FastAPI · Next.js · Deck.gl · MapLibre (sense claus dAPI)
---
## Arquitectura
```
trajectories/
├── backend/ # API i dades
│ ├── main.py # FastAPI: metadata, blocs JSON/Arrow, CORS, gzip
│ ├── data/ # Dades servides per lAPI
│ │ ├── 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.json` i blocs de frames (JSON o **Arrow IPC**). Les dades viuen a `backend/data/` o `backend/data/simulations/<sim_id>/`. LAPI accepta `?sim=default` (o qualsevol `sim_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 el `currentTime` i 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
```bash
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 dun 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
```
LAPI queda disponible a **http://localhost:8000**.
### 2. Frontend
```bash
cd frontend
npm install
npm run dev
```
Obre **http://localhost:3000**. Per defecte el frontend crida lAPI a `http://localhost:8000` (configurable amb `NEXT_PUBLIC_API_URL` si cal).
### 3. Ús bàsic
1. Backend en marxa (terminal 1), frontend en marxa (terminal 2).
2. Obrir http://localhost:3000.
3. Tancar/acceptar el popup dintroducció i esperar que carreguin els blocs (barra de progrés).
4. 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 dIDs 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`.