Developer Guide
Build from source, modify the GUI, and contribute to PIVTools.
Getting the Source
PIVTools is split across two repositories.
Backend + Processing
Flask server, PIV processing engine, C extensions, and CLI.
git clone https://github.com/MTT69/python-PIVTOOLs.git
cd python-PIVTOOLsFrontend (React)
Next.js web interface. Only needed if you want to modify the GUI.
git clone https://github.com/MTT69/PIVTOOLs-GUI.git
cd PIVTOOLs-GUIBuilding C Extensions
PIVTools includes three C libraries compiled via setup.py. There are no external C dependencies -- the FFT engine is a code-generated SIMD codelet kernel and the peak fitter is a hand-rolled Levenberg-Marquardt, so FFTW and GSL are not needed (every kernel is original work shipped under GPL-3.0-or-later, linking only OpenMP and libm). The only requirement is an OpenMP-capable clang toolchain.
libbulkxcorr2dSIMD codelet FFT cross-correlation + LM peak fitting (OpenMP)
libfusedwarpFused symmetric image warping for multipass deformation (OpenMP)
libkspacefitk-space transfer-function LM fitter for ensemble PIV, one fit per window (OpenMP). Built as its own library because it must compile with no architecture or SIMD flags.
Build Steps
Install the package in editable mode (this compiles the C extensions), with the optional dev/cine extras for tests and Phantom .cine support:
# Editable install -- compiles all three C libraries into pivtools_cli/lib/
pip install -e ".[dev,cine]"
# Recompile the C extensions after editing C sources
python setup.py buildThe Python side loads the compiled libraries via ctypes by absolute path from pivtools_cli/lib/, so a rebuild is picked up without reinstalling -- just restart the GUI/CLI. Nothing recompiles automatically after a C edit, so always rebuild before running.
The FFT engine is generated for a fixed set of interrogation window sizes -- 8, 12, 16, 24, 32, 48, 64, 96, 128. Config validation rejects any other window size at load time, with one exception: on an ensemblesingle-mode pass the window size is a Frame-A mask support rather than an FFT length, so 4 and 6 are also accepted there.
Builds never use -ffast-math, and the SIMD output is validated bit-identical to the old FFTW build. Floating-point contraction is set per translation unit rather than globally: the FFT units build with-ffp-contract=fast, while the LM peak fitter andlibkspacefit build with-ffp-contract=off, because FMA contraction perturbs Levenberg-Marquardt convergence.
Platform Requirements
| Platform | Compiler | Setup |
|---|---|---|
| macOS (Apple Silicon) | clang (Homebrew LLVM) | brew install llvm libomp -- auto-detected, no CC needed |
| Windows | clang-cl | Visual Studio "Desktop development with C++" workload plus the "C++ Clang tools for Windows" component |
| Linux | clang | sudo apt install clang libomp-dev |
Windows: x64 Native Tools Command Prompt Required
All commands (pip install -e . and python setup.py build) must be run from the x64 Native Tools Command Prompt for VS (or a shell where vcvars64.bat has been called). A plain Command Prompt, PowerShell, or VS Code terminal fails with clang-cl not found.
Find it in Start Menu → Visual Studio → x64 Native Tools Command Prompt for VS 2022. Set PIVTOOLS_WIN_COMPILER to a specific clang-cl.exe, or to cl to force plain MSVC (the batched SIMD peak fitter is unavailable under plain cl).
End Users: No Compiler Needed
PyPI wheels ship with pre-compiled .dll/.so files. Running pip install pivtools just works.
One wheel per platform serves every Python 3.12+: Linux x86_64 (manylinux_2_28, glibc 2.28+), macOS arm64 (macOS 15+, floor set by the bundled Homebrew libomp), and Windows AMD64. Linux and Windows wheels enforce an AVX2+FMA CPU floor at load time (pivtools_cpu_supported()) -- pre-Haswell CPUs get a clear error pointing at the source install.
Build Tuning
All build knobs are environment variables read by setup.py at build time. Local source builds default to native tuning (-march=native / -mcpu=native); PyPI wheels pin portable flags instead.
| Variable | Default | Effect |
|---|---|---|
PIVTOOLS_FFT_ISA | neon4 (macOS arm64), vext8 (Linux x86_64), avx2 (Windows) | SIMD lane width of the codelet FFT and batched peak fitter (one PIV window per lane). avx512 is available for HPC but is a measured loss on AMD Zen 4 (double-pumped AVX-512) -- keep vext8 there; it only pays on true-512-bit Intel nodes. |
PIVTOOLS_FFT_MARCH | platform arch flag (native) | Replaces the FFT arch flag verbatim (e.g. -march=icelake-server). Important on HPC: native bakes in the build host's ISA, so build on a compute node or pin this explicitly. |
PIVTOOLS_WARP_MARCH | platform arch flag (native) | Same override for libfusedwarp's SIMD warp kernel. |
PIVTOOLS_FFT_LTO | off | 1 enables link-time optimisation for the FFT translation units. |
PIVTOOLS_WIN_COMPILER | VS-bundled clang-cl | Path to a specific clang-cl.exe, or cl to force MSVC. |
CC | clang (macOS/Linux) | Explicit compiler override on macOS/Linux (e.g. CC=gcc). There is no silent fallback -- missing clang is a hard error. |
PIVTOOLS_FFT_ISA=avx512 \
PIVTOOLS_FFT_MARCH='-march=icelake-server' \
PIVTOOLS_WARP_MARCH='-march=icelake-server' \
pip install -e .The build prints what it resolved (isa=... lanes=... arch=...) and emits a NOTICE whenever a native arch flag is in play. See BUILD-SIMD.md in the repository for per-platform build and verification recipes.
GUI Development
The GUI is a Next.js React app served as static files by the Flask backend.
# Clone and install
git clone https://github.com/MTT69/PIVTOOLs-GUI.git
cd PIVTOOLs-GUI
npm install
# Development server with hot reload
npm run dev
# Build for production
npm run buildDeploying GUI Changes
After building, deploy the compiled output to the backend:
- Run
npm run buildto create theout/folder - Copy
out/topython-PIVTOOLs/pivtools_gui/ - Rename it to
static(replacing the existing folder) - Run
pivtools-guito see your changes
Running the Code
After building from source, PIVTools provides two interfaces. Both use the same config.yaml.
GUI
pivtools-gui
# or
python pivtools_gui/app.pyOpens at localhost:5000
CLI
pivtools-cli <command>
# init, instantaneous, ensemble,
# transform, merge, statistics, videoSee CLI Reference for all commands
Changes made in the GUI are saved to config.yaml. The CLI reads from the same file, so you can configure in the GUI and run batch processing from the terminal.
Ready to Configure?
Learn how to set up your image paths, camera configuration, and file formats.
Image Configuration Guide