Live site: https://app.wisprlabs.com/
The backend lives under backend/src and exposes both REST and GraphQL interfaces for the wildfire spread model checkpoint in backend/resources/model.ckpt. It expects the pre-generated HDF5 cubes under ../HDF5/<year> (relative to the repository root), which matches the layout you shared.
- Activate the provided conda environment when running commands:
conda run -n wildfire python --version
- Ensure the following Python packages are available in the
wildfireenvironment:fastapi,strawberry-graphql,uvicorn[standard],torch,torchvision,segmentation-models-pytorch,pytorch-lightning,h5py.
From the repository root:
conda run -n wildfire uvicorn main:app --app-dir backend/src --reload --host 0.0.0.0 --port 8000The app loads the PyTorch Lightning checkpoint once at startup, scans the HDF5 directory for available fires, and serves both REST (/health, /catalog, /findSpread) and GraphQL (/graphql) endpoints.
Environment variables (optional overrides):
| Variable | Default | Description |
|---|---|---|
HDF5_ROOT |
../HDF5 (relative to repo root) |
Absolute or relative path to the folder that contains yearly subfolders with .hdf5 cubes. |
MODEL_CHECKPOINT |
backend/resources/model.ckpt |
Path to the Lightning checkpoint to load. |
WSTS_ROOT |
../../../src/wsts/ (relative to directory of wsts_bridge.py) |
Path to WildfireSpreadTS (wsts) source code directory root. |
WILDFIRE_DEFAULT_YEAR |
2021 |
Year used when the client does not specify one. |
WILDFIRE_STATS_YEARS |
2018,2019 |
Training years whose statistics are used for feature standardization. |
WILDFIRE_N_LEADS |
1 |
Number of leading observations to feed into the model per prediction. |
WILDFIRE_PROB_THRESHOLD |
0.5 |
Default probability cutoff when converting model logits to a binary mask. |
WILDFIRE_DEVICE |
auto-detect | Set to cpu, cuda, etc. to pin inference to a specific device. |
WILDFIRE_INFER_MAX_CONCURRENCY |
3 |
Maximum concurrent inference requests handled by the backend app. |
WILDFIRE_INFER_QUEUE_TIMEOUT_SECONDS |
0.35 |
Queue wait timeout before backend rejects inference with 429. |
WILDFIRE_CACHE_TTL_SECONDS |
600 |
TTL for cached inference probability rasters. |
WILDFIRE_CACHE_MAX_ENTRIES |
300 |
Maximum in-memory inference cache entries (LRU eviction). |
GET /health– returns model/device status plus resolved paths.GET /catalog?year=2021&limit=50&offset=0– lists available fires (id, extent, number of samples) for the requested year.POST /findSpread– body:Responds with metadata plus a GeoJSON FeatureCollection embedding:{ "fireId": "fire_24935867", "year": 2021, "sampleOffset": -1, "probabilityThreshold": 0.5 }- Centroid coordinates from the HDF5 attributes (
lnglat) so the client can place the feature on a basemap. - The predicted probability raster and binary mask for the requested sample window.
- Basic summary stats (mean/max probabilities, positive pixel counts, etc.).
- Under high load, this endpoint and
/fires/{fire_id}/layersmay return429 Too Many Requests.
- Centroid coordinates from the HDF5 attributes (
The deployment uses layered protections:
- Edge/network protections (rate limit + continuous monitoring).
- Nginx route-level request throttling with
429fallback. - Backend concurrency guard and fail-fast queue timeout for inference endpoints.
Available at /graphql. Example query:
query {
catalog(year: 2021, limit: 5) {
fireId
year
samples
}
findSpread(fireId: "fire_24935867") {
fire {
fireId
latitude
longitude
}
threshold
geojson
}
}The GraphQL types mirror the REST responses and surface the same GeoJSON payload for easy client reuse.
Components of the WildfireSpreadPrediction application are containerized for ease of setup and execution.
Assume the below commands should be run from the repository root (WildfireSpreadPrediction/). If using a different
container runtime/CLI, substitute podman with this (e.g. docker).
Before building and deploying, make sure that the environment variables and configuration files are set correctly. These include:
- The
composeenvironment variables (e.g../local.env) - The
viteenvironment variables (i.e../frontend/wildfireFE/.env) - The
nginxconfiguration (i.e../nginx/nginx.conf), as well as SSL/TLS certificate, if applicable
For convenience, all necessary container images and builders can be run with a few simple commands using compose profiles.
For a complete rebuild of both the frontend and backend, as well as to re-deploy the web server/proxy and backend:
podman compose --profile build --podman-build-args "--network host" build # builds frontend builder and backend base image
podman compose --profile web-build run frontend-build # runs frontend builder to create dist/ directory and assets
podman compose up -d --build # builds backend image and runs wispr-web and wispr-backend containersTo rebuild only the frontend, re-build and re-run the builder, then restart the web server:
podman compose --profile web-build --podman-build-args "--network host" build # builds the frontend builder image
podman compose --profile web-build run frontend-build # runs the frontend builder image to create dist/
podman compose restart web # restarts the web server to use new frontend files
# # alternatively, if web server/proxy container needs to be recreated, due to e.g. change in the image:
# podman compose up -d web # redeploys web containerTo rebuild only the backend, (optionally) re-build the base image and re-build the backend image, then re-deploy the backend:
podman compose --profile backend-build --podman-build-args "--network host" build # builds backend base image
# ^^ Optional, only if base image does not need rebuild (i.e. no requirements changes)
podman compose up -d --build backend # builds backend image and runs backend containerThe frontend builder image installs the required Node modules and prepares for a production build.
Using the files in the repository, running the container is equivalent to performing a vite build
operation locally, but does not require Node etc. installations on the host. It is designed to generate
the build files in a bind-mounted volume so that they can be accessed on the host by the production web server.
To build the frontend builder image, run:
# podman build --network host -f frontend/frontend.build.Containerfile -t wispr-frontend-build .
podman compose --profile web-build --podman-build-args "--network host" build # use compose build so that image tags are correct (underscores)To run the frontend builder image (to build frontend files, dist/), use Compose:
podman compose --profile web-build run frontend-buildAfter the container runs, the production web files should be generated and accessible in the specified host directory.
The backend base image packages Python and most libraries for convenience. Separation of the backend base image from the final, runnable image allows for quicker builds, assuming there are no major changes of requirements.
To build the backend base image, run:
# podman build --network host -f backend/backend.base.Containerfile -t wispr-backend-base .
podman compose --profile backend-build --podman-build-args "--network host" build # use compose build - In RHEL/SELinux enabled operating systems, builds may fail without additional configuration.
For ease of execution, this can be run as root with
sudo(note that the built image will then only be accessible to root) - The
--network hostflag may not be needed depending on network settings, but helps avoid e.g. DNS issues for installing dependencies within container
Once the backend base image is built or pulled, it can be used as the base image to build the final backend image. The build process for this image should just be to copy the source code into the container image, but if additional or modified requirements are needed, these can also be installed at this stage for development/debugging purposes. However, it is recommended that the final changes in requirements be eventually migrated in the base image, too, in order to minimize build time for the final image.
To build the backend image, run:
# podman build -f backend/backend.Containerfile -t wispr-backend .
podman compose build wispr-backend- The same notes as above apply, especially if installing additional requirements
Alternatively, this step can be skipped if the --build flag is used with the podman compose up command below.
For convenience, it is easiest to run the application containers using podman compose.
The compose.yaml file defines several services, the main ones being frontend and backend.
For each service, the following may be defined:
- Which Containerfile is used to build the container image
- What command to execute when running the container
- What environment variables to set in the container
- Which ports to map from the host to the container
- Which volumes to mount into the container
... and so on. This avoids having to manually set these as flags in regular podman commands (e.g. build, run).
To bring up the application, the simplest option is to run:
podman compose up -dThe --build flag should be added if the backend image was not already built.
Then, to stop and remove the container(s), run:
podman compose downTo bring up or down only a specific container:
podman compose up <container-name> -d
podman compose down <container-name>