|
| 1 | +--- |
| 2 | +name: pivpy |
| 3 | +description: >- |
| 4 | + Expert skill for deep Particle Image Velocimetry (PIV) vector field analysis, post-processing, |
| 5 | + vortex topology identification, spatial filtering, outlier cleaning, and publication-ready figures/reports. |
| 6 | + Designed to work in tandem with openpiv-skill and scientific reporting workflows. |
| 7 | +--- |
| 8 | + |
| 9 | +# PIVPy Skill: Deep PIV Analysis, Visualization & Reporting |
| 10 | + |
| 11 | +This skill equips the agent with comprehensive domain expertise, workflows, and code recipes for processing, analyzing, and visualizing Particle Image Velocimetry (PIV) data using **PIVPy** (built on top of `xarray`, `numpy`, `scipy`, and `matplotlib`). |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## 1. System Architecture & Interoperability |
| 16 | + |
| 17 | +``` |
| 18 | ++---------------------+ +----------------------+ +-----------------------+ |
| 19 | +| Raw Image Pairs | ----> | openpiv-skill | ----> | Raw Velocity Fields | |
| 20 | +| (TIF, BMP, PNG) | | (cross-correlation) | | (TXT, DAT, VC7, NC) | |
| 21 | ++---------------------+ +----------------------+ +-----------+-----------+ |
| 22 | + | |
| 23 | + v |
| 24 | ++------------------------------------------------------------------------------------+ |
| 25 | +| PIVPy Skill | |
| 26 | +| | |
| 27 | +| 1. Canonical Ingestion: build_dataset(), load_directory(), from_openpiv() | |
| 28 | +| 2. Validation & Clean: normalized_median_test(), clean(), harmonic inpainting | |
| 29 | +| 3. Spatial Filtering: smooth(method='gaussian' | 'median' | 'butterworth') | |
| 30 | +| 4. Kinematic & Topology: vorticity, Gamma1, Gamma2, Q-criterion, Okubo-Weiss | |
| 31 | +| 5. Gradient & Strain: gradient_tensor(), max_shear(), acceleration() | |
| 32 | +| 6. Turbulence & Spectra: Reynolds decomposition, E(k), dissipation, R_ij(r) | |
| 33 | +| 7. Publication Figures: piv.plot(), marimo notebooks, animations, LaTeX reports| |
| 34 | ++------------------------------------------------------------------------------------+ |
| 35 | +``` |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## 2. Canonical Data Model (`xarray.Dataset`) |
| 40 | + |
| 41 | +Every PIV field in PIVPy is represented as an `xarray.Dataset` containing: |
| 42 | +- **Dimensions**: `('y', 'x')` for single frames, `('y', 'x', 't')` for time series / ensembles. |
| 43 | +- **Coordinates**: |
| 44 | + - `x`: 1D array of horizontal positions $[x_0, x_1, \dots, x_{N-1}]$. |
| 45 | + - `y`: 1D array of vertical positions $[y_0, y_1, \dots, y_{M-1}]$. |
| 46 | + - `t`: 1D array of time stamps or frame indices $[t_0, t_1, \dots, t_{K-1}]$ (optional). |
| 47 | +- **Required Data Variables**: |
| 48 | + - `u`: Horizontal velocity component $[M \times N]$ or $[M \times N \times K]$. |
| 49 | + - `v`: Vertical velocity component $[M \times N]$ or $[M \times N \times K]$. |
| 50 | + - `chc`: Vector validation flag channel ($1.0 = \text{valid}$, $0.0 = \text{spurious/outlier}$). |
| 51 | +- **Attributes (`attrs`)**: `units_x`, `units_y`, `units_u`, `units_v`, `units_t`, `dt`, `history`. |
| 52 | + |
| 53 | +--- |
| 54 | + |
| 55 | +## 3. Standard PIV Processing Pipeline |
| 56 | + |
| 57 | +### Step 1: Ingestion from OpenPIV or Files |
| 58 | + |
| 59 | +```python |
| 60 | +import xarray as xr |
| 61 | +import pivpy.pivpy # Registers .piv accessor |
| 62 | +from pivpy import io |
| 63 | + |
| 64 | +# Option A: From OpenPIV output files / directories |
| 65 | +ds = io.load_directory("path/to/openpiv_results/", extension=".txt") |
| 66 | + |
| 67 | +# Option B: From OpenPIV arrays directly in memory |
| 68 | +from pivpy.schema import build_dataset |
| 69 | +ds = build_dataset(x=x, y=y, u=u, v=v, chc=flags, dt=0.001) |
| 70 | + |
| 71 | +# Option C: Out-of-core streaming from Zarr archive |
| 72 | +ds = io.open_zarr("dataset.zarr") |
| 73 | +``` |
| 74 | + |
| 75 | +### Step 2: Outlier Rejection & Inpainting (Normalized Median Test) |
| 76 | + |
| 77 | +```python |
| 78 | +# Westerweel & Scarano (2005) Normalized Median Test + Harmonic Inpainting |
| 79 | +ds_clean = ds.piv.clean( |
| 80 | + method="normalized_median", |
| 81 | + threshold=2.0, # Residual threshold (typically 2.0) |
| 82 | + epsilon=0.1, # Velocity noise floor |
| 83 | + inpaint_method=0, # 0 = harmonic Laplacian, 1 = nearest, 2 = linear |
| 84 | + radius=1, # 3x3 stencil (radius=1) or 5x5 stencil (radius=2) |
| 85 | +) |
| 86 | +``` |
| 87 | + |
| 88 | +### Step 3: Spatial Filtering & Denoising |
| 89 | + |
| 90 | +```python |
| 91 | +# Gaussian smoothing |
| 92 | +ds_smooth = ds_clean.piv.smooth(sigma=1.2, method="gaussian") |
| 93 | + |
| 94 | +# Frequency-domain Butterworth filter |
| 95 | +ds_bw = ds_clean.piv.smooth(sigma=8.0, method="butterworth", order=2.0) |
| 96 | +``` |
| 97 | + |
| 98 | +### Step 4: Vortex Identification & Kinematic Diagnostics |
| 99 | + |
| 100 | +```python |
| 101 | +# 1. Circulation-based noise-robust vorticity (77% error reduction vs standard diff) |
| 102 | +ds_vort = ds_smooth.piv.vorticity(name="vorticity", method="circulation", radius=2) |
| 103 | + |
| 104 | +# 2. Topology Identification: Gamma1 (vortex center) and Gamma2 (boundary) |
| 105 | +ds_g1 = ds_smooth.piv.gamma1(name="gamma1", radius=3) |
| 106 | +ds_g2 = ds_smooth.piv.gamma2(name="gamma2", radius=3) |
| 107 | + |
| 108 | +# 3. Galilean-invariant Q-criterion & Okubo-Weiss parameter |
| 109 | +ds_q = ds_smooth.piv.q_criterion(name="Q") |
| 110 | +ds_ow = ds_smooth.piv.okubo_weiss(name="OW") |
| 111 | + |
| 112 | +# 4. Solid-body rotation subtraction |
| 113 | +ds_nobr = ds_smooth.piv.subsbr() |
| 114 | +``` |
| 115 | + |
| 116 | +### Step 5: Velocity Gradient & Acceleration Analysis |
| 117 | + |
| 118 | +```python |
| 119 | +# Full strain rate tensor decomposition |
| 120 | +tensor = ds_smooth.piv.gradient_tensor(return_components=True) |
| 121 | +# Contains: s_xx, s_yy, s_xy, lambda_1, lambda_2, max_shear, strain_angle |
| 122 | + |
| 123 | +# Total Material Acceleration D(u)/Dt (unsteady + convective) |
| 124 | +ds_accel = ds_smooth.piv.acceleration(name="accel", unsteady=True) |
| 125 | +``` |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +## 4. Publication-Ready Visualizations |
| 130 | + |
| 131 | +### Beautiful Single-Frame Quiver & Contour Plots |
| 132 | + |
| 133 | +```python |
| 134 | +import matplotlib.pyplot as plt |
| 135 | + |
| 136 | +# Generate high-contrast, publication-quality figure |
| 137 | +fig, ax = plt.subplots(figsize=(7, 5), dpi=300) |
| 138 | + |
| 139 | +ds.piv.plot( |
| 140 | + flow_property="vorticity", # Background scalar |
| 141 | + cmap="RdBu_r", # Diverging colormap |
| 142 | + clim=(-15, 15), # Symmetric color limits |
| 143 | + cbar=True, |
| 144 | + cbar_label=r"Vorticity $\omega_z$ [s$^{-1}$]", |
| 145 | + quiver_scale=1.0, # Optimized arrow scaling |
| 146 | + quiver_density=2, # Subsample grid for clear arrow visibility |
| 147 | + quiver_color="k", |
| 148 | + quiver_width=0.003, |
| 149 | + quiver_alpha=0.75, |
| 150 | + ax=ax, |
| 151 | +) |
| 152 | + |
| 153 | +ax.set_xlabel(r"$x$ [mm]", fontsize=12) |
| 154 | +ax.set_ylabel(r"$y$ [mm]", fontsize=12) |
| 155 | +ax.set_title("Vortical Wake Evolution", fontsize=14, pad=10) |
| 156 | +fig.tight_layout() |
| 157 | +fig.savefig("figure_vortex_wake.pdf", bbox_inches="tight") |
| 158 | +``` |
| 159 | + |
| 160 | +### Fluid Dynamics Quiver Animation (MP4 / GIF) |
| 161 | + |
| 162 | +```python |
| 163 | +anim = ds.piv.animate( |
| 164 | + flow_property="vorticity", |
| 165 | + cmap="Spectral_r", |
| 166 | + quiver_scale=0.8, |
| 167 | + quiver_density=3, |
| 168 | + quiver_color="midnightblue", |
| 169 | + quiver_width=0.0035, |
| 170 | + quiver_alpha=0.7, |
| 171 | + fps=15, |
| 172 | + blur=0.6, |
| 173 | + save_path="vortex_pair_dynamics.gif", |
| 174 | +) |
| 175 | +``` |
| 176 | + |
| 177 | +--- |
| 178 | + |
| 179 | +## 5. Automated Deep PIV Analysis Reports |
| 180 | + |
| 181 | +When generating comprehensive analysis reports for experiments: |
| 182 | +1. **Quality Audit Table**: Report total vectors, percentage of valid vs inpainted vectors, mean velocity magnitude, peak Reynolds stresses, and vortex core circulation $\Gamma$. |
| 183 | +2. **Multi-Panel Overview**: |
| 184 | + - Panel A: Streamwise & transverse velocity contours ($u, v$). |
| 185 | + - Panel B: Circulation vorticity & $\Gamma_2$ vortex boundary contours. |
| 186 | + - Panel C: $Q$-criterion & Okubo-Weiss topology partitioning. |
| 187 | + - Panel D: Maximum shear strain rate & material acceleration. |
| 188 | +3. **Artifact Generation**: Save high-resolution PNG/PDF figures and export analysis summary markdown artifacts. |
0 commit comments