Skip to content

MovingUniverseLab/spisea-web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SPISEA Web — Cluster CMD Explorer

A small web app that wraps SPISEA with a FastAPI backend and a React + Vite + TypeScript frontend so you can explore synthetic clusters, isochrones, color–magnitude diagrams, and unresolved spectra interactively in the browser.

This repository is a thin client around the SPISEA Python package. It does not modify or vendor SPISEA — spisea must be importable in the Python environment that runs the backend.

Originally created for Dan Weisz's Stellar Pops class. Code and documentation generated with support from Cursor.

Requirements

  • Python 3.10+ (the backend uses PEP 604 union syntax such as list[str] | None).
  • Node.js 18+ and npm for the frontend.
  • A working SPISEA install plus its data dependencies. See SPISEA's setup notes for the full list. At a minimum you need:
    • pysynphot and a CDBS data tree (typically pointed to via PYSYN_CDBS)
    • SPISEA's evolution / atmosphere model data (SPISEA_MODELS)
    • SPISEA's filt_func/ directory (SPISEA_FILT_FUNC, see below)
  • The COSMIC evolution model is optional. To use it (and edit its BSEDict binary-evolution parameters in the UI) you must also install COSMIC (pip install cosmic-popsynth) in the backend environment. COSMIC evolves binaries directly, so it requires a multiplicity model; the IFMR and unresolved-spectrum options are ignored when it is selected.

Installing SPISEA

The backend imports spisea directly. Pick one of:

# Option 1: install from GitHub (cleanest for deployments)
pip install git+https://github.com/astropy/SPISEA.git

# Option 2: install an editable copy from a local SPISEA checkout
pip install -e /path/to/SPISEA

If you use Option 1, the SPISEA filt_func/ data directory (which lives at the SPISEA repo root, not inside the spisea/ package) will not be present. In that case set SPISEA_FILT_FUNC to point at a filt_func/ directory from a SPISEA checkout, e.g.:

export SPISEA_FILT_FUNC=/path/to/SPISEA/filt_func

If you use Option 2, the bridge auto-discovers filt_func/ next to the SPISEA checkout, so SPISEA_FILT_FUNC is optional.

Backend

cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# plus SPISEA itself, see above
uvicorn app.main:app --reload --port 8000

The API listens on http://127.0.0.1:8000 and exposes /api/meta, /api/cluster, /api/cluster-fits, /api/cluster-fits-batch, /api/cluster-notebook, and /api/isochrone-cmd.

Useful environment variables

Variable Purpose
SPISEA_FILT_FUNC Path to SPISEA's filt_func/ directory (filter discovery).
PYSYN_CDBS CDBS root for pysynphot (atmosphere & throughput tables).
SPISEA_MODELS SPISEA evolution/atmosphere model directory.
SPISEA_WEB_ISO_DIR Where the backend caches IsochronePhot FITS files.
SPISEA_WEB_CDBS_FILTER_MAX Cap on CDBS throughput files enumerated for filter list.
SPISEA_WEB_STATIC_DIR Directory of the built frontend the backend serves at / (production only; defaults to /app/static).

Tests

cd backend
pytest

The API tests reuse SPISEA's bundled isochrone fixtures via os.path.dirname(spisea.__file__)/tests/isochrones, so they require an installed SPISEA whose tests/isochrones/ directory is present (e.g. an editable install from a SPISEA git checkout).

Frontend

cd frontend
npm install
npm run dev

Vite serves on http://127.0.0.1:5173 and proxies /api/* to the backend at http://127.0.0.1:8000 (see frontend/vite.config.ts).

For a production build:

npm run build
npm run preview

Layout

spisea-web/
  backend/            FastAPI app + SPISEA bridge
    app/
      main.py         FastAPI routes
      bridge.py       SPISEA object construction, isochrone cache, serializers
      models.py       Pydantic request/response models
      web_filter_aliases.py
    tests/
    requirements.txt
  frontend/           React + Vite + TS SPA
    src/App.tsx       Main UI (CMD, mass function, spectrum panels)
    vite.config.ts    Dev proxy to the backend

Deploying on NERSC SPIN

In production the app runs as a single container: the FastAPI backend serves both the built frontend (at /) and the /api/* routes, so no separate web server is needed. SPISEA and its data are bind-mounted from CFS rather than baked into the image, and COSMIC is installed in the image.

Deployment files in this repo:

File Purpose
Dockerfile Multi-stage build: Vite build, then a Python runtime that serves static assets + the API.
docker-entrypoint.sh Adds the mounted SPISEA checkout (SPISEA_SRC, default /spisea) to PYTHONPATH and ensures the cache dir exists.
backend/requirements-spisea.txt SPISEA's scientific dependencies + cosmic-popsynth (SPISEA source itself comes from CFS).
.dockerignore Keeps build context small.
deploy/spin/*.yaml Reference Deployment / Service / Ingress manifests (templates with <PLACEHOLDER>s).

Prerequisites

  • A NERSC account with your project visible in SPIN, plus completed SpinUp training and access to registry.nersc.gov.
  • A SPISEA checkout and its data trees staged on CFS, for example:
/global/cfs/cdirs/<PROJECT>/spisea-web/
  SPISEA/        # full SPISEA git checkout (spisea/ package + filt_func/)
  data/cdbs/     # -> PYSYN_CDBS=/data/cdbs
  data/models/   # -> SPISEA_MODELS=/data/models

Ensure the directories are traversable (o+x from root to the mount point) so SPIN can bind-mount them.

1. Build and push the image

From a NERSC login node (or anywhere with the NERSC registry):

TAG="registry.nersc.gov/<PROJECT>/<NAMESPACE>/spisea-web:v1"
podman-hpc build -t "$TAG" .      # or: docker build -t "$TAG" .
podman-hpc push "$TAG"

2. Deploy in Rancher

Log in to https://rancher2.spin.nersc.gov/, pick the development or production cluster, and create/select a namespace in your project. Then either:

  • Apply the manifests in deploy/spin/ after replacing every <PLACEHOLDER> (image, namespace, NERSC UID/GID, CFS paths), or
  • Recreate the equivalent settings in the Rancher UI (Workloads → Create → Deployment), using deploy/spin/deployment.yaml as the checklist.

Key SPIN requirements baked into the manifests:

  • Pull secret registry-nersc (required even for public images).
  • Container name must stay container-0 (renaming triggers a Rancher UI bug).
  • Security context: drop ALL capabilities, add back only NET_BIND_SERVICE; set runAsUser/runAsGroup/fsGroup to your NERSC UID/GID (required for the CFS mounts).
  • Storage: read-only CFS bind-mounts for the SPISEA checkout and data, plus a writable nfs-client-vast PVC for SPISEA_WEB_ISO_DIR.

3. Expose it

Create a ClusterIP service on port 8000 (deploy/spin/service.yaml) and an nginx Ingress (deploy/spin/ingress.yaml). The generated host is <ingress>.<namespace>.<environment>.svc.spin.nersc.org (note .org).

The Ingress sets proxy-read/send/connect-timeout: "900" because COSMIC cluster runs can take up to 900s (see _COSMIC_TIMEOUT_SEC in backend/app/main.py); without this, long runs return 504 Gateway Timeout. For a public HTTPS URL, CNAME a custom domain to the generated host and attach a TLS certificate secret to the Ingress.

Verifying

Use Execute shell on the pod in Rancher:

python -c "import spisea; print(spisea.__file__)"
echo "$PYSYN_CDBS $SPISEA_MODELS"
curl -s http://127.0.0.1:8000/api/meta | head

License

GPL v3+ (see LICENSE). SPISEA itself is GPL v3+.

About

SPISEA Web Calculator

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors