Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
9fbaca4
Initial push
ErichZimmer May 8, 2023
c422b91
Moved files to main module
ErichZimmer May 8, 2023
5b4d902
Further refinements
ErichZimmer May 8, 2023
08ec59e
Removed nesting
ErichZimmer May 8, 2023
711df0c
Further refinements and bug fixes
ErichZimmer May 8, 2023
eb5e6ae
Add marker detection
ErichZimmer May 23, 2023
9281d81
Revise calibration utils
ErichZimmer Jun 1, 2023
ad02894
Revise polynomial calibration
ErichZimmer Jun 1, 2023
f41dcb6
Revise pinhole calibration
ErichZimmer Jun 1, 2023
b1250f9
Fix example typos
ErichZimmer Jun 1, 2023
8f183e6
Fix example typos
ErichZimmer Jun 1, 2023
7118eb5
Bug fixes
ErichZimmer Jun 1, 2023
5e2af06
Revised pinhole distortion model
ErichZimmer Jun 2, 2023
8322ca2
Minor typo in error
ErichZimmer Jun 2, 2023
a8173d5
Further enhancements
ErichZimmer Jun 2, 2023
fdf0072
Code aesthetics
ErichZimmer Jun 2, 2023
7a938f5
Code readability
ErichZimmer Jun 3, 2023
12df23f
Add error for minimum points
ErichZimmer Jun 3, 2023
274eb63
New marker detector
ErichZimmer Jun 3, 2023
c7de5ac
Typos
ErichZimmer Jun 3, 2023
f98fece
Refined get_markers_local
ErichZimmer Jun 5, 2023
1fa733d
Remove unnecessary parameter
ErichZimmer Jun 5, 2023
cc4d4ee
Added preprocessing routines
ErichZimmer Jun 6, 2023
85f1158
Removed image file to upload push
ErichZimmer Jun 6, 2023
e4e4925
Major Revision
ErichZimmer Jun 16, 2023
4d50209
Add ignored test file
ErichZimmer Jun 16, 2023
bb20268
Fixed unit testing
ErichZimmer Jun 17, 2023
bddb572
Added polynomial distortion correction
ErichZimmer Jul 10, 2023
7182f8e
Unit Testing
ErichZimmer Jul 11, 2023
f48905c
ENH: Unit testing
ErichZimmer Aug 25, 2023
a243637
Revised calibration module and features
ErichZimmer Dec 9, 2023
ae5041d
Removed artifact file
ErichZimmer Dec 9, 2023
a7a5709
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Dec 11, 2023
3056814
Revised corner detection
ErichZimmer Dec 11, 2023
1298dce
Merge branch '#220-calibration' of https://github.com/ErichZimmer/ope…
ErichZimmer Dec 11, 2023
be8ca66
Fixed missing corner orientation
ErichZimmer Dec 11, 2023
92ce4a5
Revised marker detection
ErichZimmer Dec 14, 2023
ef2dd55
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer May 26, 2024
07e4d32
Added tests
ErichZimmer May 26, 2024
45fd190
Revised camera models
ErichZimmer May 26, 2024
c02ef43
Revised camera module
ErichZimmer May 26, 2024
bcfa0cd
Wrong DLT algorithm
ErichZimmer May 26, 2024
2a12e3c
Revised camera models
ErichZimmer May 31, 2024
05e6094
Revised tests
ErichZimmer May 31, 2024
3dc8227
Enhanced calibration utilities
ErichZimmer Jun 5, 2024
eaa071b
More testing
ErichZimmer Jun 5, 2024
c3bc29b
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Jun 11, 2024
9c41a93
Revised documentation
ErichZimmer Jun 13, 2024
f1d54c0
Merge branch '#220-calibration' of https://github.com/ErichZimmer/ope…
ErichZimmer Jun 13, 2024
cef1926
More testing
ErichZimmer Jun 13, 2024
257480c
Forced push test files
ErichZimmer Jun 13, 2024
2bbbd94
Added missing image set
ErichZimmer Jun 15, 2024
2226ad8
Fixed epipolar bugs
ErichZimmer Jun 15, 2024
9157cf6
Updated marker detection
ErichZimmer Jun 16, 2024
203efa1
Bug fix
ErichZimmer Jun 17, 2024
583f385
Add Multiple Line Intersection
ErichZimmer Jun 25, 2024
d82ee0c
Add tests for multi line intersects
ErichZimmer Jun 25, 2024
c73a1c5
Update docstring
ErichZimmer Jun 25, 2024
146ca3f
Update docstring again
ErichZimmer Jun 25, 2024
a7f3c9e
Fix tests
ErichZimmer Jun 27, 2024
1ec32ca
Refactor and enhance
ErichZimmer Jun 28, 2024
1e22719
had two issues: one is some text in the __init__.py and some related …
alexlib Jun 29, 2024
09b8a5e
Re-wrote DLT camera model
ErichZimmer Jun 29, 2024
89bf998
Syntax error
ErichZimmer Jun 29, 2024
c29becb
Re-wrote functions
ErichZimmer Jun 29, 2024
3671e97
Updated docstring
ErichZimmer Jun 29, 2024
3e5266a
Bug fixes
ErichZimmer Jun 29, 2024
5e38e94
Fix DLT model
ErichZimmer Jun 29, 2024
f68d79b
Patch DLT unit tests
ErichZimmer Jun 29, 2024
ceaf859
Fix relative import
ErichZimmer Jun 29, 2024
0bbfb4a
Revised tests with MyPTV example data
ErichZimmer Jun 30, 2024
2c19162
Re-wrote pinhole camera model
ErichZimmer Jun 30, 2024
1324ef9
Updated tests
ErichZimmer Jun 30, 2024
5fb7cdf
Added more cameras for testing
ErichZimmer Jun 30, 2024
320ddbe
Removed uneeded import
ErichZimmer Jun 30, 2024
f94a012
Updated poly model
ErichZimmer Jun 30, 2024
aeb8d2c
Updated poly testing
ErichZimmer Jun 30, 2024
9bf6e4e
Revised some stuff
ErichZimmer Jun 30, 2024
e32d628
Fixed some stuff
ErichZimmer Jun 30, 2024
dc4a615
Update docstring
ErichZimmer Jun 30, 2024
e536c96
Update docstring
ErichZimmer Jun 30, 2024
39dcb13
Update conf.py
alexlib Jun 30, 2024
ad036cb
Merge branch '#220-calibration' of https://github.com/ErichZimmer/ope…
alexlib Jun 30, 2024
613d9cc
Bug fix
ErichZimmer Jul 2, 2024
e998a53
Simplified docstring
ErichZimmer Jul 2, 2024
a365979
Add MyPTV distortion algorithm
ErichZimmer Jul 2, 2024
cb463a6
Bug fix
ErichZimmer Jul 2, 2024
934ee1b
fixed the option to run pytest from the root folder
alexlib Jul 11, 2024
7230472
also polynomial test
alexlib Jul 11, 2024
cb43550
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Aug 20, 2024
747f21e
Bug fix point search algo
ErichZimmer Aug 21, 2024
a33010f
More testing
ErichZimmer Aug 21, 2024
36d4049
More testing
ErichZimmer Aug 21, 2024
2429d0a
Oops, wrong file
ErichZimmer Aug 21, 2024
998ba7b
Refined some tests
ErichZimmer Aug 21, 2024
f4ccde1
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Oct 27, 2024
c5a3bab
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer May 20, 2025
0dd0f41
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Aug 31, 2025
271cf1d
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Mar 8, 2026
d925f0a
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer May 10, 2026
0902a69
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Jul 21, 2026
918f9d0
Merge branch 'OpenPIV:master' into #220-calibration
ErichZimmer Sep 6, 2026
62a541b
Merge main into pr/324
alexlib Oct 12, 2026
2f79ff4
stereo calibration of davis set
alexlib Oct 12, 2026
6289d5d
Update .gitignore
alexlib Oct 15, 2026
1356689
docs: stereo calibration theory, workflow and API reference
alexlib Oct 15, 2026
0818ca6
Updated Soloff model with custom ray-based polynomial back projection
ErichZimmer Oct 17, 2026
f914149
Forgot to update etsts
ErichZimmer Oct 17, 2026
7a688c3
Improved DLT model performance
ErichZimmer Oct 17, 2026
2c7f6de
Fixed DLT nonlinear refinement
ErichZimmer Oct 17, 2026
3adfa01
Added two line triangulation in polynomial model
ErichZimmer Oct 17, 2026
15da455
Fixed pinhole minimization (or at least more correct)
ErichZimmer Oct 17, 2026
151a507
Add missing checkerboaard corner detection
ErichZimmer Oct 18, 2026
d279288
Minor changes
ErichZimmer Oct 18, 2026
9bc66db
Merge branch '#220-calibration' of https://github.com/ErichZimmer/ope…
alexlib Oct 19, 2026
7ba45ca
Add stereo-PIV example package, ruff gate, and fix disparity sign
alexlib Oct 19, 2026
a5290d7
Add the cycle survey and the DaVis comparison to the stereo example
alexlib Oct 19, 2026
fa684c0
New marching algorithm for automated matching
ErichZimmer Oct 20, 2026
8c91600
Some refactors
ErichZimmer Oct 20, 2026
ffc7a90
Updated error and string style
ErichZimmer Oct 20, 2026
0eb1e70
Merge branch '#220-calibration' of https://github.com/ErichZimmer/ope…
ErichZimmer Oct 20, 2026
0683f9c
VS code docstring shenanigans
ErichZimmer Oct 20, 2026
488a19a
Merge branch '#220-calibration' of ErichZimmer/openpiv-python into pr…
alexlib Oct 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ crates/**/target/
dist/
*.whl
/piv_explainer
/.agents
/.claude
skills-lock.json

# artifacts written by the tests into the working directory
/minimized
/saved_params
/dummy
14 changes: 11 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ OpenPIV is a Python library for Particle Image Velocimetry (PIV) analysis of flu

### Bootstrap and Install Dependencies
- Use Poetry: `pip install poetry` then `poetry install` (~10 seconds). All development commands should use `poetry run <command>`.
- The Rust acceleration is optional: `maturin develop --release -m crates/openpiv_rust/Cargo.toml` builds it in place. Without it the SciPy backend is used.

### Build and Test
- Run tests: `poetry run pytest openpiv -v` — ~10 seconds, 216 tests pass.
- **Always run the tests and ruff before committing.** Both are required, a green
test suite alone is not enough.
- Run tests: `poetry run pytest openpiv -v` — ~10 seconds, ~350 tests pass.
- Run a single test file: `poetry run pytest openpiv/test/test_process.py -v`
- Lint: `poetry run ruff check .` (config in `pyproject.toml`, `[tool.ruff]`).
`poetry run ruff check . --fix` applies the safe fixes; the unsafe ones
(`--unsafe-fixes`) can change runtime behaviour and need a test run afterwards.
- Import test: `poetry run python -c "import openpiv; print('OpenPIV imported successfully')"`
- No linting tools are configured (no black, flake8, etc.).
- No formatting tool is configured; ruff's linter is the style gate.
- `python setup.py build_ext --inplace` is a legacy no-op: all Cython (`.pyx`) files have been removed and converted to pure Python, despite the package description still mentioning "Cython modules".

### Run Example Workflows
Expand All @@ -38,6 +44,8 @@ OpenPIV is a Python library for Particle Image Velocimetry (PIV) analysis of flu
- `preprocess.py` — image preprocessing (background subtraction, masking).
- `smoothn.py` — robust spline smoothing; a Python port of `smoothn.m` (D. Garcia / Prof. Lewis) bundled for convenience — it is not covered by the OpenPIV license, see README for attribution.
- `phase_separation.py` — solid-phase / liquid-tracer separation utilities.
- `calibration/` — camera calibration: `dlt_model/`, `pinhole_model/`, `poly_model/` (Soloff) and `stereo.py` (common world grid, dewarp, disparity self-calibration, 3C reconstruction). The sub-package uses duck typing: a camera needs `project_points`, `project_to_z`, `resolution` and `dtype`.
- `examples/stereo/` — runnable stereo-PIV example on DaVis data: `config.py` (`StereoConfig`), `davis.py` (DaVis XML exports), `frames.py` (`.ims`/`.im7` via the optional `readim7` dependency), `pipeline.py` (the steps), `__main__.py` (CLI: `info`, `calibrate`, `dewarp`, `disparity`, `piv`, `all`).

### Typical call chains
- Quick path: `piv.simple_piv(frame_a, frame_b, plot=False)` → `(x, y, u, v, s2n)`.
Expand All @@ -46,7 +54,7 @@ OpenPIV is a Python library for Particle Image Velocimetry (PIV) analysis of flu
- Batch/multi-pass: build a `PIVSettings`, then `windef.piv(settings)`.

### Tests
- `openpiv/test/` (~216 tests). `conftest.py` forces the `Agg` matplotlib backend and patches `plt.show` so tests run headless — keep that in mind if adding plotting code.
- `openpiv/test/` (~350 tests). `conftest.py` forces the `Agg` matplotlib backend and patches `plt.show` so tests run headless — keep that in mind if adding plotting code.

### Packaging notes
- Package name on PyPI is `OpenPIV`; import name is lowercase `openpiv`.
Expand Down
1 change: 1 addition & 0 deletions benchmarks/fft_backends/bench_repeated_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
its upfront planning cost. Throwaway script for explore/fft-backends.
"""
import time

import numpy as np

N_CALLS = 40 # ~ processing 40 image pairs at one pass/window size
Expand Down
3 changes: 2 additions & 1 deletion benchmarks/fft_backends/bench_single_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
branch. Run with: uv run python scripts_bench_fft.py
"""
import time

import numpy as np


Expand Down Expand Up @@ -95,7 +96,7 @@ def main():
dt, out = bench(a, b, run)
results[backend_name] = (dt, out)
print(f" {backend_name:20s} {dt*1000:8.2f} ms")
except Exception as e: # noqa: BLE001 - benchmark script, report and continue
except Exception as e:
print(f" {backend_name:20s} FAILED: {e}")

if "scipy.fft" in results:
Expand Down
15 changes: 9 additions & 6 deletions benchmarks/fft_backends/benchmark_windef.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import time
import tempfile
import pathlib
import tempfile
import time

import numpy as np
from imageio.v3 import imwrite

from openpiv import windef
from openpiv.settings import PIVSettings
from openpiv.test import test_process


def run_multigrid(frame_a, frame_b, backend, n_runs=3):
settings = PIVSettings()
settings.windowsizes = (64, 32, 16)
Expand All @@ -16,10 +19,10 @@ def run_multigrid(frame_a, frame_b, backend, n_runs=3):
settings.sig2noise_validate = False
settings.show_all_plots = False
settings.show_plot = False

# Warmup
windef.multigrid_windef(frame_a, frame_b, settings)

times = []
for _ in range(n_runs):
t0 = time.perf_counter()
Expand Down Expand Up @@ -52,14 +55,14 @@ def run_mp(frame_a, frame_b, backend):
settings.save_plot = False
settings.show_all_plots = False
settings.sig2noise_validate = False

t0 = time.perf_counter()
windef.piv(settings)
return (time.perf_counter() - t0) * 1000.0

def main():
frame_a, frame_b = test_process.create_pair(image_size=256)

print("=" * 60)
print(" BENCHMARK: Multigrid Window Deformation (256x256, 3 passes)")
print("=" * 60)
Expand Down
27 changes: 14 additions & 13 deletions benchmarks/fft_backends/run_piv_quiver_demo.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import os
import time
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
from importlib.resources import files
from openpiv import pyprocess, tools, validation, filters
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import openpiv_rust

from openpiv import filters, pyprocess, tools, validation

ARTIFACT_DIR = Path(r"C:\Users\alex\.gemini\antigravity-cli\brain\371a4578-c887-4c4a-bba3-7bbfb7f1997c")
ARTIFACT_DIR.mkdir(parents=True, exist_ok=True)

Expand All @@ -27,7 +29,7 @@ def run_real_piv_demo():

# 1. Scipy correlation
t0 = time.perf_counter()
scipy_corr = pyprocess.fft_correlate_images(aa, bb, correlation_method="circular", normalized_correlation=False)
pyprocess.fft_correlate_images(aa, bb, correlation_method="circular", normalized_correlation=False)
t_scipy_corr = time.perf_counter() - t0

# 2. Rust correlation
Expand Down Expand Up @@ -71,7 +73,7 @@ def run_real_piv_demo():

# Plot Quiver Comparison
fig, axes = plt.subplots(1, 3, figsize=(18, 5.5), facecolor="white")

# Panel 1: Scipy
ax = axes[0]
ax.imshow(frame_a, cmap="gray", alpha=0.5, origin="upper")
Expand Down Expand Up @@ -111,7 +113,7 @@ def run_synthetic_vortex_demo():
print("\n=== Running Synthetic Vortex Quiver Demo ===")
np.random.seed(42)
img_h, img_w = 256, 256

n_particles = 4000
px = np.random.uniform(0, img_w, n_particles)
py = np.random.uniform(0, img_h, n_particles)
Expand All @@ -124,31 +126,30 @@ def run_synthetic_vortex_demo():
ry = py - cy
r = np.sqrt(rx**2 + ry**2) + 1e-6
v_theta = gamma * r / (r0**2 + r**2)

dx_particles = -v_theta * (ry / r)
dy_particles = v_theta * (rx / r)

frame_a = np.zeros((img_h, img_w), dtype=np.float32)
frame_b = np.zeros((img_h, img_w), dtype=np.float32)

for i in range(n_particles):
x0, y0 = int(round(px[i])), int(round(py[i]))
x0, y0 = round(px[i]), round(py[i])
if 1 <= x0 < img_w - 1 and 1 <= y0 < img_h - 1:
frame_a[y0, x0] += 200.0
frame_a[y0+1, x0] += 100.0
frame_a[y0-1, x0] += 100.0
frame_a[y0, x0+1] += 100.0
frame_a[y0, x0-1] += 100.0

x1, y1 = int(round(px[i] + dx_particles[i])), int(round(py[i] + dy_particles[i]))
x1, y1 = round(px[i] + dx_particles[i]), round(py[i] + dy_particles[i])
if 1 <= x1 < img_w - 1 and 1 <= y1 < img_h - 1:
frame_b[y1, x1] += 200.0
frame_b[y1+1, x1] += 100.0
frame_b[y1-1, x1] += 100.0
frame_b[y1, x1+1] += 100.0
frame_b[y1, x1-1] += 100.0

window_size = 32
overlap = 16
search_area_size = 32

Expand All @@ -158,7 +159,7 @@ def run_synthetic_vortex_demo():

# Scipy correlation
t0 = time.perf_counter()
scipy_corr = pyprocess.fft_correlate_images(aa, bb, correlation_method="circular", normalized_correlation=False)
pyprocess.fft_correlate_images(aa, bb, correlation_method="circular", normalized_correlation=False)
t_scipy_corr = time.perf_counter() - t0

# Rust correlation
Expand All @@ -173,7 +174,7 @@ def run_synthetic_vortex_demo():
x, y = pyprocess.get_coordinates(image_size=frame_a.shape, search_area_size=search_area_size, overlap=overlap)

fig, axes = plt.subplots(1, 2, figsize=(14, 6), facecolor="white")

# Panel 1: Rust Quiver Field
ax = axes[0]
ax.imshow(frame_a, cmap="gray", alpha=0.5, origin="upper")
Expand Down
4 changes: 3 additions & 1 deletion benchmarks/fft_backends/test_rust_fft.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import sys
import time

import numpy as np
from openpiv import pyprocess
import openpiv_rust

from openpiv import pyprocess

print('=== OpenPIV Rust vs scipy.fft Benchmark & Validation ===', flush=True)

# Shapes representing real PIV interrogation window batches
Expand Down
2 changes: 2 additions & 0 deletions benchmarks/run_benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
python benchmarks/run_benchmarks.py
"""
import time

import numpy as np

from openpiv import pyprocess, validation, windef
from openpiv.settings import PIVSettings

Expand Down
42 changes: 42 additions & 0 deletions dummy
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
dummy
512 512
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
1.0 1.0
0.0 1.0
2.0 3.0
4.0 5.0
6.0 7.0
8.0 9.0
10.0 11.0
12.0 13.0
14.0 15.0
16.0 17.0
18.0 19.0
20.0 21.0
22.0 23.0
24.0 25.0
26.0 27.0
28.0 29.0
30.0 31.0
32.0 33.0
34.0 35.0
36.0 37.0
38.0 39.0
float64
31 changes: 15 additions & 16 deletions openpiv/PIV_3D_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"""


from itertools import chain

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from itertools import chain
from mpl_toolkits.mplot3d import Axes3D


def set_axes_equal(ax):
Expand All @@ -21,8 +21,8 @@ def set_axes_equal(ax):
Parameters
----------
ax: matplotlib.axes object
"""

x_limits = ax.get_xlim3d()
Expand Down Expand Up @@ -202,7 +202,7 @@ def quiver_3D(
arrow_scale=0.15,
equal_ax=True,
):
"""
"""
Displaying 3D deformation fields vector arrows
Parameters
Expand All @@ -217,33 +217,33 @@ def quiver_3D(
mask_filtered, boolean 3d ndarray or 1d ndarray
Array, or list with same dimensions as the deformations. Defines the area where deformations are drawn
filter_def: float
Filter that prevents the display of deformations arrows with length < filter_def
filter_reg: tuple,list or int
Filter that prevents the display of every i-th deformations arrows separatly alon each axis.
filter_reg=(2,2,2) means that only every second arrow along x,y z axis is displayed leading to
a total reduction of displayed arrows by a factor of 8. filter_reg=3 is interpreted
as (3,3,3).
cmap: string
matplotlib colorbar that defines the coloring of the arrow
quiv_args: dict
Dictionary with kwargs passed on to the matplotlib quiver function.
vmin,vmax: float
Upper and lower bounds for the colormap. Works like vmin and vmax in plt.imshow().
arrow_scale: float
Automatic scaling of the quiver arrows so that the longest arrow has the
Automatic scaling of the quiver arrows so that the longest arrow has the
length axis length * arrow_scale. Arrow length can alternatively be set by
passing a "lenght" argument in quiv_args.
passing a "lenght" argument in quiv_args.
equal_axes: bool
resize the figure axis so that they are have equal scaling.
Returns
-------
Expand Down Expand Up @@ -283,8 +283,7 @@ def quiver_3D(
x, y, z = np.indices(u.shape)
else:
raise ValueError(
"displacement data has wrong number of dimensions (%s). Use 1d array, list, or 3d array."
% str(len(u.shape))
f"displacement data has wrong number of dimensions ({len(u.shape)!s}). Use 1d array, list, or 3d array."
)

# conversion to array
Expand Down
1 change: 0 additions & 1 deletion openpiv/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from importlib.metadata import version


__version__ = version("OpenPIV")


Expand Down
Loading
Loading