PIV Processing

Configure multi-pass cross-correlation for instantaneous or ensemble analysis.

Overview

InstantaneousEnsemble
OutputVelocity field per frame pairSingle mean velocity field
CorrelationPer frame pairAveraged across all pairs
Use caseTime-resolved data, turbulence statisticsMean flow, low seeding, max resolution
Pass typesStandard onlyStandard + Single mode
Peak finderConfigurable (gauss3-6)Configurable (default gauss6)
Live previewYes (per-frame)No (accumulated)
ResumeNoYes (resume_from_pass)

Window Configuration

Both modes use multi-pass refinement. Each pass refines results from the previous one. Configure passes in the GUI pass table or directly in YAML.

ParameterFormatDescription
window_size[Height, Width]Interrogation window in pixels per pass. Must be powers of 2. Rectangular windows supported.
overlapinteger (%)Overlap percentage per pass. 50% doubles grid density.
runslist of pass numbersWhich passes to save (1-based). Last pass always saved.
type (ensemble)'std' | 'single'Standard or single-pixel mode per pass.

Window size convention: [Height, Width] (row-major). Height = vertical (Y), Width = horizontal (X). Use rectangular windows for directional flows (e.g., [32, 64] for predominantly horizontal flow).

config.yaml
# Typical 3-pass configuration instantaneous_piv: window_size: - [128, 128] # Pass 1: large windows - [64, 64] # Pass 2: refinement - [32, 32] # Pass 3: final overlap: - 50 - 50 - 50 runs: - 3 # Save pass 3 only

Single Mode and Sum Window

Ensemble only. Appears when any pass uses type single.

Single mode uses asymmetric window weighting: Frame A gets a small central window (the configured window_size), Frame B gets the full sum_window. This concentrates the measurement on a small region while computing correlations at the larger FFT size.

ParameterDescriptionConstraint
sum_windowFFT correlation window size [H, W]Must be >= window_size
sum_fitting_windowCentral extraction for fitting (optional)Reduces memory and speeds fitting
config.yaml
ensemble_piv: window_size: - [128, 128] # Pass 1: std - [64, 64] # Pass 2: std - [16, 16] # Pass 3: single type: - std - std - single sum_window: - 64 - 64 # [Height, Width] for single passes

Camera Selection

Select which cameras to process via numbered chips in the GUI. At least one must be selected. In YAML, set paths.camera_numbers.

Peak Finding

Both modes. Instantaneous defaults to gauss3. Ensemble defaults to gauss6.

AlgorithmDOFDescription
gauss33Parabolic (1D Gaussian). Fastest.
gauss44Circular Gaussian with amplitude.
gauss55Elliptical Gaussian. Good for anisotropic flows.
gauss66Rotated elliptical Gaussian. Maximum accuracy.
config.yaml
instantaneous_piv: peak_finder: gauss3 # Options: gauss3, gauss4, gauss5, gauss6

Predictor & Peak Settings

Control how the predictor field is refined between multi-pass iterations and configure multi-peak detection.

SettingDefaultModeDescription
predictor_smoothingtrue / falseInst / EnsGaussian-smooth the predictor between passes. Recommended for instantaneous (reduces single-pair noise). For ensemble, smoothing can destroy real gradients — leave disabled unless data is very noisy.
predictor_interpolationcubicEnsembleInterpolation for upscaling the predictor field between passes. Options: linear or cubic.
image_warp_interpolationcubicBothInterpolation kernel for image warping during predictor deformation. cubic = bicubic (4×4 stencil), lanczos = Lanczos-3 (6×6 stencil, slightly sharper).
secondary_peakfalseInstantaneousExtract the second-highest correlation peak per window. Useful for reverse flow or multiple particle populations.
num_peaks1InstantaneousNumber of correlation peaks to detect per window. Usually 1; increase for multi-peak analysis.
save_modeminimalInstantaneousOutput fields per vector file. 'minimal' saves ux, uy, b_mask only (fastest). 'full' saves all 11 fields including peak height, sigma, stresses.
save_compressionfalseInstantaneousEnable ZLIB compression on .mat output files. Slower writes but smaller file size.
config.yaml
instantaneous_piv: predictor_smoothing: true secondary_peak: false num_peaks: 1 save_mode: minimal save_compression: false image_warp_interpolation: cubic ensemble_piv: predictor_smoothing: false predictor_interpolation: cubic image_warp_interpolation: cubic

Boundary Conditions

Ensemble only. Overrides edge-replicated predictor padding near walls with prescribed velocity values.

In wall-bounded flows, the predictor field near boundaries can be corrupted by edge replication. Boundary conditions let you prescribe known velocities (e.g., no-slip: ux=0, uy=0) at specific wall positions.

FieldTypeDescription
y_positionint (px)Row position of the wall in the image
uxfloat (px/frame)Prescribed horizontal displacement at the wall
uyfloat (px/frame)Prescribed vertical displacement at the wall
edge'bottom' | 'top'Which image edge the wall is near
config.yaml — no-slip walls at top and bottom
ensemble_piv: predictor_boundary_conditions: - y_position: 10 ux: 0 uy: 0 edge: bottom - y_position: 950 ux: 0 uy: 0 edge: top

Correlation & Fitting

Ensemble only. Advanced controls for peak fitting and memory management.

SettingDefaultDescription
fit_offsettrueInclude a constant offset in the Gaussian sub-pixel fit. Accounts for correlation plane background level.
mask_center_pixeltrueMask the autocorrelation center pixel before peak fitting. Prevents the zero-lag spike from biasing displacement estimates.
persist_imagesfalseKeep all filtered images in worker RAM across passes. Faster on HPC with lots of memory, but significantly increases RAM usage.
sum_fitting_window_enabledfalseExtract a central sub-region from the summed correlation plane before peak fitting. Reduces memory and speeds up fitting.
sum_fitting_window[16, 16]Size [H, W] of the central extraction window. Only active when sum_fitting_window_enabled is true.
config.yaml
ensemble_piv: fit_offset: true mask_center_pixel: true persist_images: false sum_fitting_window_enabled: false sum_fitting_window: - 16 - 16

Ensemble Options

Ensemble only. Available in the collapsible Ensemble Options panel.

SettingDefaultDescription
fit_methodkspace'kspace' (Fourier-space, 5-param, default, 50-100x faster) or 'gaussian' (Levenberg-Marquardt, 16-param). K-space recommended for all use cases.
background_subtraction_methodcorrelation'correlation': R = <AB> - <A><B> (single-pass, memory efficient). 'image': R = <(A-μA)(B-μB)> (two-pass, more stable for k-space)
gradient_correctionfalseReynolds stress gradient correction near walls
kspace_soft_weightingtrueAnisotropic soft spectral weighting in k-space fitting. Improves Reynolds stress accuracy, especially at small window sizes.
kspace_k_max_cap0.35Maximum wavenumber cap for k-space fitting (0.0-0.5). Controls the spectral bandwidth used for displacement estimation.
store_planesfalseSave AA, BB, AB correlation planes to disk (large files)
save_diagnosticsfalseSave debug images and peak fitting data to filters/ directory
resume_from_pass0Resume from pass N (1-based). 0 = fresh start. Requires existing ensemble_result.mat.

Performance Settings

Configure parallel processing resources. Applies to both modes.

SettingDefaultDescription
backendcpuProcessing backend
omp_threads4OpenMP threads per worker for C extensions
dask_workers_per_node2Number of parallel Dask workers
dask_memory_limit8GBRAM allocation per worker
dask_max_in_flight_per_worker3Max concurrent tasks queued per worker. Higher values (4-6) improve I/O pipelining on HPC with fast storage.
open_dashboardfalseAuto-open the Dask performance dashboard in your browser when processing starts
cluster_typelocal'local' or 'slurm'
filter_worker_count1Workers for preprocessing. Set 1 for temporal filters, 2+ for spatial-only.
auto_compute_paramsfalseAuto-compute omp_threads, dask_workers, and dask_memory from system resources
n_nodes1Number of compute nodes (SLURM cluster only)
slurm_walltime01:00:00Job walltime for SLURM submissions
slurm_partition(none)SLURM partition name
post_processing_workersautoMax parallel workers for calibration, statistics, merge, and transform. auto = min(cpu_count, 16)
config.yaml
processing: backend: cpu omp_threads: 4 dask_workers_per_node: 2 dask_memory_limit: 8GB dask_max_in_flight_per_worker: 3 open_dashboard: false cluster_type: local filter_worker_count: 1

Outlier Detection

Identify and mark spurious vectors for replacement. Multiple methods can be chained. Instantaneous and ensemble use separate config sections.

MethodParametersDescription
peak_magthreshold: 0.4Reject vectors with correlation peak below threshold
median_2depsilon: 0.2, threshold: 2.0Normalised median test against 8 neighbours
Instantaneous
outlier_detection: enabled: true methods: - type: peak_mag threshold: 0.4 - type: median_2d epsilon: 0.2 threshold: 2
Ensemble
ensemble_outlier_detection: enabled: true methods: - type: median_2d epsilon: 0.2 threshold: 2

Infilling

Replace outlier vectors (NaN) with interpolated values. Applied in two phases: mid-pass (between passes, always enabled) and final-pass (on output, optional).

MethodParametersDescription
local_medianksize: 3Median of neighbours. Fast, small gaps.
biharmonic(none)PDE-based smooth interpolation. High quality.
knnn_neighbors: 32, weights: 'distance'Distance-weighted regression. Sparse data.
config.yaml
infilling: # or ensemble_infilling: mid_pass: method: biharmonic # no parameters needed final_pass: enabled: true method: biharmonic # no parameters needed

NaN Reason Codes

Every interrogation window is assigned a nan_reason code indicating why it was marked invalid, or 0 if it passed all checks. This field is saved in the output .mat file and is shared by both Gaussian and k-space fitters.

CodeStageDescription
-1Pre-fittingMasked vector (outside ROI / polygon mask)
0SuccessFit succeeded and passed all validation checks
1FittingSolver did not converge (LM for Gaussian, TRF for k-space)
2Post-fit validationAB peak height invalid (Gaussian) or SNR too low (k-space)
3Post-fit validationDisplacement exceeds 3/4 window rule (peak too far from centre)
5Post-fit validationNegative sigma / variance values (unphysical fit)
6Displacement checkDisplacement exceeds 3/4 window rule (checked in accumulator)
10Outlier detectionVelocity outlier: fit succeeded but flagged by median-based displacement outlier detection
11Outlier detectionStress outlier: fit succeeded but flagged by stress field median test or Cauchy-Schwarz realizability violation (ensemble only)
Validation pipeline order
  1. Fitter attempts fit (codes 1, 2)
  2. Post-fit parameter validation (codes 3, 5)
  3. Displacement magnitude check in accumulator (code 6)
  4. Velocity outlier detection via median test (code 10)
  5. Stress outlier detection + realizability check, ensemble final pass only (code 11)
  6. Vectors with code 0 after all checks are valid

Codes 3 and 6 both enforce the 3/4 displacement rule but at different stages: code 3 is checked inside the fitter, code 6 in the accumulator after the fitter returns. Vectors flagged with codes 10 or 11 are infilled from neighbours if infilling is enabled.

Running PIV

Start processing from the Run PIV card. Select which source/base path pairs to process via checkboxes.

Workflow

  1. Check the datasets to include. Same PIV settings apply to all selected paths.
  2. Click Run PIV. If output already exists, a confirmation dialog asks to clear and recompute.
  3. Monitor progress via the progress bar (instantaneous) or console logs (both modes).
  4. Cancel gracefully if needed. Partial results may be saved.
Instantaneous feedback

Progress bar, live vector field preview (variable selector, colormap), console logs.

Ensemble feedback

Status indicator + console logs only. No preview until all pairs are accumulated.

config.yaml
# Enable one mode at a time processing: instantaneous: true ensemble: false

Complete YAML Reference

YAML PathInst.Ens.Description
processing.instantaneousY-Enable instantaneous mode
processing.ensemble-YEnable ensemble mode
*_piv.window_sizeYYList of [H, W] per pass
*_piv.overlapYYOverlap % per pass
*_piv.runsYYPasses to save (1-based)
*_piv.peak_finderYYgauss3 (inst default) / gauss4 / gauss5 / gauss6 (ens default)
*_piv.predictor_smoothingYYSmooth predictor between passes (inst: true, ens: false)
instantaneous_piv.secondary_peakY-Detect secondary correlation peak (default false)
instantaneous_piv.num_peaksY-Number of peaks to detect (default 1)
ensemble_piv.type-YPer-pass: std or single
ensemble_piv.sum_window-Y[H, W] for single mode
ensemble_piv.fit_method-Ygaussian or kspace
ensemble_piv.kspace_soft_weighting-YSoft spectral weighting for k-space (default true)
ensemble_piv.kspace_k_max_cap-YMax wavenumber cap (default 0.35)
ensemble_piv.background_subtraction_method-Ycorrelation or image
ensemble_piv.gradient_correction-YReynolds stress gradient correction
ensemble_piv.fit_offset-YInclude offset in Gaussian fit (default true)
ensemble_piv.mask_center_pixel-YMask autocorrelation center pixel (default true)
ensemble_piv.persist_images-YKeep filtered images in worker RAM (default false)
ensemble_piv.predictor_interpolation-YPredictor upscaling: linear or cubic
ensemble_piv.image_warp_interpolation-YImage warp kernel: cubic or lanczos
instantaneous_piv.image_warp_interpolationY-Image warp kernel: cubic or lanczos (default cubic)
instantaneous_piv.save_modeY-minimal (3 fields) or full (11 fields)
instantaneous_piv.save_compressionY-ZLIB compression on .mat files (default false)
ensemble_piv.predictor_boundary_conditions-YWall boundary conditions array
ensemble_piv.sum_fitting_window_enabled-YExtract central sub-region for fitting
ensemble_piv.sum_fitting_window-Y[H, W] extraction size (default [16,16])
ensemble_piv.store_planes-YSave correlation planes
ensemble_piv.save_diagnostics-YSave debug data
ensemble_piv.resume_from_pass-Y0 = fresh, N = resume from pass N
outlier_detection.*Y-enabled, methods: [{type, threshold, epsilon}]
ensemble_outlier_detection.*-YSame structure as outlier_detection
infilling.*Y-mid_pass + final_pass config
ensemble_infilling.*-YSame structure as infilling
processing.omp_threadsYYOpenMP threads (default 4)
processing.dask_workers_per_nodeYYDask workers (default 2)
processing.dask_memory_limitYYPer-worker RAM (default 8GB)
processing.dask_max_in_flight_per_workerYYMax tasks per worker (default 3)
processing.open_dashboardYYAuto-open Dask dashboard (default false)
processing.cluster_typeYYlocal or slurm
processing.auto_compute_paramsYYAuto-compute worker/thread settings (default false)
processing.post_processing_workersYYParallel post-processing workers (default auto)
processing: instantaneous: true ensemble: false backend: cpu omp_threads: 4 dask_workers_per_node: 2 dask_memory_limit: 8GB dask_max_in_flight_per_worker: 3 open_dashboard: false cluster_type: local filter_worker_count: 1 auto_compute_params: false post_processing_workers: null instantaneous_piv: window_size: - [128, 128] - [64, 64] - [32, 32] overlap: - 50 - 50 - 50 runs: - 3 peak_finder: gauss3 predictor_smoothing: true secondary_peak: false num_peaks: 1 image_warp_interpolation: cubic save_mode: minimal save_compression: false ensemble_piv: window_size: - [128, 128] - [64, 64] - [16, 16] overlap: - 50 - 50 - 50 type: - std - std - single runs: - 3 sum_window: - 64 - 64 fit_method: kspace background_subtraction_method: correlation gradient_correction: false kspace_soft_weighting: true kspace_k_max_cap: 0.35 fit_offset: true mask_center_pixel: true persist_images: false predictor_smoothing: false predictor_interpolation: cubic image_warp_interpolation: cubic predictor_boundary_conditions: [] sum_fitting_window_enabled: false sum_fitting_window: - 16 - 16 store_planes: false save_diagnostics: false resume_from_pass: 0 outlier_detection: enabled: true methods: - type: peak_mag threshold: 0.4 - type: median_2d epsilon: 0.2 threshold: 2 ensemble_outlier_detection: enabled: true methods: - type: median_2d epsilon: 0.2 threshold: 2 infilling: mid_pass: method: biharmonic parameters: {} final_pass: enabled: true method: biharmonic parameters: {} ensemble_infilling: mid_pass: method: biharmonic parameters: {} final_pass: enabled: true method: biharmonic parameters: {}

Command Line Usage

Terminal
# Run instantaneous PIV pivtools-cli instantaneous # Run ensemble PIV pivtools-cli ensemble # Process specific paths only (0-indexed) pivtools-cli instantaneous -p 0,2 # Override active paths pivtools-cli ensemble --active-paths 0,1
CommandDescription
pivtools-cli initCreate default config.yaml
pivtools-cli instantaneousRun instantaneous PIV
pivtools-cli ensembleRun ensemble PIV
pivtools-cli apply-calibrationApply calibration to vectors
pivtools-cli statisticsCompute statistics
pivtools-cli transformApply geometric transforms
pivtools-cli mergeMerge multi-camera fields
pivtools-cli videoCreate visualisation videos

All commands read settings from config.yaml in the current directory. Use -p 0,1 to override paths.active_paths. Use --help for command-specific options.

Next: Calibration

Convert pixel displacements to physical velocities.

Planar Calibration Guide