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-PIVTOOLs

Frontend (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-GUI

Building 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.

libbulkxcorr2d

SIMD codelet FFT cross-correlation + LM peak fitting (OpenMP)

libfusedwarp

Fused symmetric image warping for multipass deformation (OpenMP)

libkspacefit

k-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 build

The 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

PlatformCompilerSetup
macOS (Apple Silicon)clang (Homebrew LLVM)brew install llvm libomp -- auto-detected, no CC needed
Windowsclang-clVisual Studio "Desktop development with C++" workload plus the "C++ Clang tools for Windows" component
Linuxclangsudo 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.

VariableDefaultEffect
PIVTOOLS_FFT_ISAneon4 (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_MARCHplatform 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_MARCHplatform arch flag (native)Same override for libfusedwarp's SIMD warp kernel.
PIVTOOLS_FFT_LTOoff1 enables link-time optimisation for the FFT translation units.
PIVTOOLS_WIN_COMPILERVS-bundled clang-clPath to a specific clang-cl.exe, or cl to force MSVC.
CCclang (macOS/Linux)Explicit compiler override on macOS/Linux (e.g. CC=gcc). There is no silent fallback -- missing clang is a hard error.
Example: pinned HPC build (Intel AVX-512 compute nodes)
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 build

Deploying GUI Changes

After building, deploy the compiled output to the backend:

  1. Run npm run build to create the out/ folder
  2. Copy out/ to python-PIVTOOLs/pivtools_gui/
  3. Rename it to static (replacing the existing folder)
  4. Run pivtools-gui to 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.py

Opens at localhost:5000

CLI

pivtools-cli <command> # init, instantaneous, ensemble, # transform, merge, statistics, video

See 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
PIVtools - High-Performance PIV Processing