Installation¶
Prerequisites¶
- Node.js 20+ (
node --versionshould show v20 or later) - Python 3.11 (3.12 also works locally; CI uses 3.11)
- Xcode Command Line Tools on macOS (
xcode-select --install). Verify the C++ toolchain actually works withnpm run check:toolchain— a macOS update can leavexcode-selectpointing at a broken Xcode, which reports as a missing compiler even though several are installed (see Troubleshooting). - For signed macOS releases (CI): an Apple Developer ID Application certificate
First-time setup¶
Four things to create: the PyHelios submodule + compiled native library, the Python venv, Node modules, and the bundled PyInstaller sidecar that the Electron app spawns (on a port chosen at runtime) in packaged builds and E2E.
PyHelios is vendored as a git submodule (built from source — there is no
pip wheel), so clone recursively and compile its native libhelios. This
needs cmake and a C++ compiler (Xcode Command Line Tools on macOS,
MSVC on Windows). The compile covers the plantarchitecture and lidar
plugins (--nogpu skips only the radiation/OptiX plugin; the lidar
CUDA ray-tracing path still compiles if a CUDA toolkit is present — see the
GPU note below). The lidar plugin
transitively builds the visualizer (OpenGL) plugin — fine on macOS and
Windows with no extra packages; on Linux you'd also need libgl1-mesa-dev,
xorg-dev, and — both for PotreeConverter — libtbb-dev and patchelf:
sudo apt-get install -y libgl1-mesa-dev xorg-dev libtbb-dev patchelf.
GPU acceleration is decided at build time
The lidar/collisiondetection plugin compiles a CUDA ray-tracing path
whenever a CUDA toolkit is found on the build machine (CMake's
find_package(CUDAToolkit) → HELIOS_CUDA_AVAILABLE); otherwise the build
is CPU/OpenMP-only. --nogpu doesn't change this — it only drops the
separate radiation/OptiX plugin. The release workflow installs the CUDA
toolkit on the Windows + Linux runners, so the shipped installers for those
platforms are GPU-capable; macOS is always CPU-only (no CUDA on Apple
hardware). cudart is linked statically, so GPU-enabled builds still run on
machines with no CUDA/driver and fall back to CPU automatically. A local
dev build is GPU-enabled only if you have a CUDA toolkit installed.
# 1. Clone the repo (recursively, to pull the PyHelios + helios-core submodules)
git clone --recursive https://github.com/PlantSimulationLab/Phytograph.git
cd Phytograph
# (already cloned non-recursively? run: git submodule update --init --recursive)
# 2. Python backend — create venv and install deps
cd backend-api
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install --upgrade pip
pip install -r requirements.txt pyinstaller # pyinstaller needed for step 5
deactivate
cd ..
# 3. Compile PyHelios from source (libhelios + editable install). A few
# minutes the first time. build-backend.mjs / dev.mjs also auto-run this
# if the native lib is missing, but doing it explicitly surfaces errors.
node scripts/build-pyhelios.mjs
# 4. Node deps
npm install
# 5. Build the Python sidecar into resources/phytograph_backend/.
npm run build:backend
Don't rely on a system-wide pyinstaller
On a dev machine with anaconda installed, a bare pyinstaller from PATH
picks up anaconda's Python — which lacks the project's deps — and
produces a broken bundle that crashes on launch. npm run build:backend
auto-discovers backend-api/venv/bin/python; override with
PYTHON=/path/to/python if needed. See the header comment of
scripts/build-backend.mjs for the full resolution logic.
Step 5 is not needed for npm run dev: with backend-api/venv present,
scripts/dev.mjs runs uvicorn directly and the Electron supervisor stands
down. Build the sidecar when you want to run the E2E suite or package an
installer. It takes a few minutes the first time; re-run only when backend code
changes. (Step 3 is the PyHelios native compile; it's a prerequisite of step 5,
which bundles libhelios into the sidecar.)
Verifying the install¶
npm run typecheck # tsc --noEmit, should succeed silently
npm run test:backend # pytest in backend-api/ (uses ./venv/bin/pytest)
npm run test:unit # vitest
If all three pass, you're ready to launch the app — see First Run.