Skills › Scientific Agent Skills › openpiv › run_example.py
run_example.py
78 lines · skills/openpiv/scripts/run_example.py at 5f2bc03
1"""End-to-end smoke test of the OpenPIV pipeline on OpenPIV's own bundled data.
3Runs the full runner.py pipeline against the exp1_001 image pair that ships inside the
4openpiv package, so it needs no external files. Use it to confirm an install works
5before pointing the CLI at real experiment data.
7 python skills/openpiv/scripts/run_example.py --output_dir /tmp/openpiv-demo
8"""
10import argparse
11import sys
12from pathlib import Path
14sys.path.insert(0, str(Path(__file__).resolve().parent))
16from analyze import PIVAnalyzer # noqa: E402
17from runner import run_openpiv # noqa: E402
20def bundled_image_pair() -> tuple[Path, Path]:
21 """Locate the exp1_001 pair inside the installed openpiv package."""
22 import openpiv
24 data_dir = Path(openpiv.__file__).parent / "data" / "test1"
25 frame_a = data_dir / "exp1_001_a.bmp"
26 frame_b = data_dir / "exp1_001_b.bmp"
27 if not frame_a.exists() or not frame_b.exists():
28 raise FileNotFoundError(
29 f"OpenPIV's bundled test1 images are missing from {data_dir}. "
30 "Pass your own image pair to runner.py instead."
31 )
32 return frame_a, frame_b
35def main() -> int:
36 parser = argparse.ArgumentParser(description=__doc__)
37 parser.add_argument("--output_dir", default="openpiv-example")
38 parser.add_argument("--window_size", type=int, default=32)
39 parser.add_argument("--overlap", type=int, default=12)
40 parser.add_argument("--search_area", type=int, default=38)
41 args = parser.parse_args()
43 frame_a, frame_b = bundled_image_pair()
44 print(f"Using bundled pair: {frame_a.name}, {frame_b.name}")
46 # dt and scaling here are the values from OpenPIV's own test1 tutorial (px/mm).
47 output_path = run_openpiv(
48 image1=str(frame_a),
49 image2=str(frame_b),
50 output_dir=args.output_dir,
51 window_size=args.window_size,
52 overlap=args.overlap,
53 search_area=args.search_area,
54 dt=0.02,
55 scaling_factor=96.52,
56 threshold=1.05,
57 verbose=True,
58 )
60 analyzer = PIVAnalyzer(output_path / "params.npz")
61 dx, dy = analyzer.grid_spacing
62 stats = analyzer.compute_statistics()
63 vorticity = analyzer.compute_vorticity()
65 print(f"\nField shape: {analyzer.u.shape}")
66 print(f"Grid spacing: dx={dx:.4f}, dy={dy:.4f} (physical units)")
67 print(f"Flagged vectors: {int(analyzer.flags.sum())}/{analyzer.flags.size}")
68 print(f"Mean velocity: u={stats['u_mean']:.4f}, v={stats['v_mean']:.4f}")
69 print(f"RMS: u={stats['rms_u']:.4f}, v={stats['rms_v']:.4f}, tke={stats['tke']:.4f}")
70 print(f"Vorticity range: {vorticity.min():.4f} to {vorticity.max():.4f}")
72 analyzer.plot_vector_field(save_path=str(output_path / "quiver.png"))
73 print(f"\nWrote quiver.png alongside runner.py's output in {output_path}")
74 return 0
77if __name__ == "__main__":
78 raise SystemExit(main())