import numpy as np
# Define PIV parameters
winsize = 32 # Interrogation window size in pixels
searchsize = 38 # Search area size in pixels
overlap = 12 # Overlap between windows (50%)
dt = 0.02 # Time between pulses in seconds
print(f"Window size: {winsize} pixels")
print(f"Search size: {searchsize} pixels")
print(f"Overlap: {overlap} pixels ({overlap/winsize*100:.0f}% overlap)")
print(f"Time step: {dt*1000:.1f} ms")First PIV Analysis - Interactive
First PIV Analysis - Interactive
This interactive tutorial provides an introduction to Particle Image Velocimetry (PIV) analysis. The code cells below are interactive - you can edit and run them in your browser!
Interrogation Window Parameters
Try adjusting the parameters and running the code:
Calculate Number of Vectors
Modify the image size and calculate the number of interrogation windows:
image_size = 256
n_windows_x = (image_size - searchsize) // overlap + 1
n_windows_y = (image_size - searchsize) // overlap + 1
total_windows = n_windows_x * n_windows_y
print(f"Image size: {image_size} x {image_size} pixels")
print(f"Interrogation windows: {n_windows_x} x {n_windows_y}")
print(f"Total vectors: {total_windows}")Velocity Calculation
Try changing the displacement values:
dx = 5.2 # Try changing this value!
dy = -3.7 # Try changing this value!
vx = dx / dt
vy = dy / dt
magnitude = np.sqrt(vx**2 + vy**2)
direction = np.arctan2(vy, vx) * 180 / np.pi
print(f"Displacement: dx = {dx:.1f} px, dy = {dy:.1f} px")
print(f"Velocity: vx = {vx:.1f} pix/s, vy = {vy:.1f} pix/s")
print(f"Magnitude: {magnitude:.1f} pix/s")
print(f"Direction: {direction:.1f} degrees")Signal-to-Noise Validation
np.random.seed(42)
snr_values = np.random.uniform(1.0, 5.0, 100)
threshold = 1.05
valid = np.sum(snr_values >= threshold)
invalid = np.sum(snr_values < threshold)
print(f"Threshold: {threshold}")
print(f"Valid vectors: {valid}/{len(snr_values)}")
print(f"Validation rate: {valid/len(snr_values)*100:.1f}%")Interactive Plot
Create a velocity field visualization:
import matplotlib.pyplot as plt
x = np.linspace(0, 256, 20)
y = np.linspace(0, 256, 20)
X, Y = np.meshgrid(x, y)
U = 10 * np.sin(2 * np.pi * X / 128)
V = 10 * np.cos(2 * np.pi * Y / 128)
fig, ax = plt.subplots(figsize=(8, 8))
Q = ax.quiver(X, Y, U, V, np.sqrt(U**2 + V**2), scale=50, pivot='middle', cmap='viridis')
ax.set_aspect('equal')
ax.invert_yaxis()
ax.set_xlabel('X (pixels)')
ax.set_ylabel('Y (pixels)')
ax.set_title('Synthetic Velocity Field')
plt.colorbar(Q, label='Velocity Magnitude (pix/s)')
plt.tight_layout()
fig