From 734751059f6228a944ccdf5032ef441b0f119993 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 19:50:02 +0000 Subject: [PATCH 1/2] chore: update copilot-instructions.md and add copilot-setup-steps.yml Agent-Logs-Url: https://github.com/OpenPIV/openpiv-python/sessions/3fb231b9-1ebc-422f-bb3b-26c6a589a7ed Co-authored-by: alexlib <747110+alexlib@users.noreply.github.com> --- .github/copilot-instructions.md | 113 +++++++++++++--------- .github/workflows/copilot-setup-steps.yml | 34 +++++++ 2 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/copilot-setup-steps.yml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 30025fe4..6167177c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,6 @@ # OpenPIV Python -OpenPIV is a Python and Cython library for Particle Image Velocimetry (PIV) analysis of fluid flow images. It provides tools for scripting and executing PIV analysis on image pairs to extract velocity fields from particle-seeded flow visualizations. The library includes both computational algorithms and optional Qt/Tk graphical user interfaces. +OpenPIV is a Python library for Particle Image Velocimetry (PIV) analysis of fluid flow images. It provides tools for scripting and executing PIV analysis on image pairs to extract velocity fields from particle-seeded flow visualizations. The library includes both computational algorithms and optional Qt/Tk graphical user interfaces. **Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.** @@ -8,7 +8,7 @@ OpenPIV is a Python and Cython library for Particle Image Velocimetry (PIV) anal ### Bootstrap and Install Dependencies - **Primary method (recommended)**: Use Poetry for development: - - Install Poetry: `pip install poetry` + - Install Poetry: `pip install poetry` - Install dependencies: `poetry install` -- takes ~10 seconds. NEVER CANCEL. - All development commands should use `poetry run ` @@ -18,9 +18,9 @@ OpenPIV is a Python and Cython library for Particle Image Velocimetry (PIV) anal - **Build from source**: `python setup.py build_ext --inplace` -- takes <1 second (no Cython extensions in current setup) ### Build and Test the Repository -- **Run tests**: `poetry run pytest openpiv -v` -- takes ~12 seconds, 198 tests pass, 12 skipped. NEVER CANCEL. Set timeout to 30+ minutes for safety. +- **Run tests**: `poetry run pytest openpiv -v` -- takes ~10 seconds, 216 tests pass. NEVER CANCEL. Set timeout to 30+ minutes for safety. - **Test import**: `poetry run python -c "import openpiv; print('OpenPIV imported successfully')"` -- **Test core functionality**: `poetry run python -c "import openpiv.piv as piv; import numpy as np; frame_a = np.random.rand(64, 64); frame_b = np.random.rand(64, 64); result = piv.simple_piv(frame_a, frame_b); print('PIV analysis completed, returned:', len(result), 'outputs')"` +- **Test core functionality**: `poetry run python -c "import openpiv.piv as piv; import numpy as np; frame_a = np.random.rand(64, 64); frame_b = np.random.rand(64, 64); result = piv.simple_piv(frame_a, frame_b, plot=False); print('PIV analysis completed, returned:', len(result), 'outputs')"` ### Run Example Workflows - **Tutorial 1**: `poetry run python openpiv/tutorials/tutorial1.py` -- demonstrates complete PIV analysis workflow @@ -31,7 +31,7 @@ OpenPIV is a Python and Cython library for Particle Image Velocimetry (PIV) anal ### ALWAYS run these validation steps after making changes: 1. **Import test**: Verify basic import works: `poetry run python -c "import openpiv"` 2. **Core functionality test**: Run simple PIV analysis to ensure algorithms work -3. **Full test suite**: `poetry run pytest openpiv -v` -- NEVER CANCEL, takes ~12 seconds but allow 30+ minutes timeout +3. **Full test suite**: `poetry run pytest openpiv -v` -- NEVER CANCEL, takes ~10 seconds but allow 30+ minutes timeout 4. **Tutorial execution**: Run `poetry run python openpiv/tutorials/tutorial1.py` to test complete workflow ### Critical User Scenarios to Test @@ -43,8 +43,8 @@ After making changes, ALWAYS test these scenarios: ### CI/CD Validation - The repository has GitHub Actions workflows in `.github/workflows/`: - - `testing.yml`: Runs tests on Python 3.10, 3.11, 3.12 with Poetry - - `build.yml`: Builds and publishes to PyPI on releases + - `testing.yml`: Runs tests on Python 3.10, 3.11, 3.12, 3.13, 3.14 with Poetry + - `build.yml`: Builds and publishes to PyPI on releases triggered by version tags - No linting tools are configured (no black, flake8, etc.) ## Common Tasks @@ -52,67 +52,88 @@ After making changes, ALWAYS test these scenarios: ### Repository Structure ``` openpiv/ -├── __init__.py # Main package initialization -├── piv.py # High-level PIV analysis functions -├── pyprocess.py # Core PIV processing algorithms -├── pyprocess3D.py # 3D PIV algorithms -├── tools.py # Utility functions for I/O and visualization -├── validation.py # Signal validation and filtering -├── filters.py # Outlier detection and replacement -├── windef.py # Window deformation PIV -├── scaling.py # Coordinate scaling and transformation -├── preprocess.py # Image preprocessing -├── smoothn.py # Smoothing algorithms -├── data/ # Sample test data -├── test/ # Comprehensive test suite (210 tests) -├── tutorials/ # Example scripts -└── docs/ # Documentation source +├── __init__.py # Package init; exposes __version__ via importlib.metadata +├── piv.py # High-level PIV workflows: simple_piv(), piv_example(), process_pair() +├── pyprocess.py # Core cross-correlation algorithms: extended_search_area_piv(), get_coordinates() +├── pyprocess3D.py # 3D PIV algorithms +├── tools.py # I/O and visualization: imread(), save(), display_vector_field(), transform_coordinates() +├── validation.py # Spurious vector detection: global_val(), global_std(), sig2noise_val() +├── filters.py # Outlier replacement: replace_outliers() (calls lib.replace_nans internally) +├── lib.py # Low-level NaN inpainting: replace_nans() (used by filters) +├── windef.py # Window-deformation iterative PIV: multipass_img_deform(), piv() +├── settings.py # PIVSettings dataclass -- required by windef batch processing +├── scaling.py # Coordinate scaling and transformation +├── preprocess.py # Image preprocessing (background subtraction, masking) +├── smoothn.py # Smoothing algorithms (robust spline smoothing) +├── phase_separation.py # Solid-phase / liquid tracer separation utilities +├── PIV_3D_plotting.py # 3D vector field plotting helpers +├── data/ # Bundled sample PIV image pairs (test1/) +├── test/ # Test suite (~216 tests); conftest.py disables matplotlib GUI +├── tutorials/ # Example scripts (tutorial1.py, tutorial2.py, windef_tutorial.py, masking_tutorial.py) +└── docs/ # Sphinx documentation source ``` ### Key APIs and Usage Patterns -- **Simple PIV**: `piv.simple_piv(frame_a, frame_b)` returns `(x, y, u, v, s2n)` -- **Extended search area**: `pyprocess.extended_search_area_piv()` for higher accuracy -- **Window deformation**: `windef` module for advanced PIV with iterative refinement -- **File I/O**: `tools.imread()`, `tools.save()`, `tools.display_vector_field()` -- **Validation**: `validation.sig2noise_val()`, `validation.global_val()` -- **Filtering**: `filters.replace_outliers()` for cleaning velocity fields +- **Simple PIV** (quickest path): `piv.simple_piv(frame_a, frame_b, plot=False)` → `(x, y, u, v, s2n)` +- **Complete workflow**: `piv.process_pair(frame_a, frame_b)` → `(x, y, u, v, mask)` +- **Core cross-correlation**: `pyprocess.extended_search_area_piv(im1, im2, window_size, overlap, search_area_size)` → `(u, v, s2n)` +- **Coordinates**: `pyprocess.get_coordinates(image_size, search_area_size, overlap)` → `(x, y)` +- **Window deformation (batch)**: `windef.piv(settings)` where `settings` is a `PIVSettings` instance +- **File I/O**: `tools.imread(path)`, `tools.save(x, y, u, v, mask, filename)`, `tools.display_vector_field(filename)` +- **Validation**: `validation.global_val(u, v, u_thresholds, v_thresholds)`, `validation.sig2noise_val(s2n, threshold)` +- **Filtering**: `filters.replace_outliers(u, v, mask, method='localmean', kernel_size=1)` +- **Coordinate transform**: `tools.transform_coordinates(x, y, u, v)` — always call before saving/displaying + +### PIVSettings (for windef batch processing) +`settings.PIVSettings` is a dataclass with defaults that point to the bundled test data. Key fields: +```python +from openpiv.settings import PIVSettings +s = PIVSettings() +s.filepath_images = pathlib.Path('path/to/images') +s.frame_pattern_a = 'frame_a_*.tif' +s.frame_pattern_b = 'frame_b_*.tif' +s.windowsizes = (64, 32, 16) # multi-pass window sizes +s.overlap = (32, 16, 8) # corresponding overlaps +s.num_iterations = 3 +``` ### Project Management -- **Dependencies**: Managed via Poetry (`pyproject.toml`) and fallback setuptools (`setup.py`) -- **Package name**: "OpenPIV" (capital letters) -- **Version**: 0.25.3 (defined in both `pyproject.toml` and `setup.py`) -- **Python support**: 3.10, 3.11, 3.12 -- **Key dependencies**: numpy, scipy, scikit-image, matplotlib, imageio +- **Dependencies**: Managed via Poetry (`pyproject.toml`); fallback setuptools config in `setup.py` +- **Package name**: `"OpenPIV"` (capital letters on PyPI, lowercase `openpiv` as import) +- **Version**: `0.25.4` (defined in both `pyproject.toml` and `setup.py`; runtime via `importlib.metadata`) +- **Python support**: 3.10, 3.11, 3.12, 3.13, 3.14 +- **Key dependencies**: numpy ≥2.0, scipy ≥1.11, scikit-image ≥0.23, matplotlib ≥3.8, imageio ≥2.35, natsort, tqdm ### Development Notes -- Uses `importlib_resources` for accessing package data files -- Test configurations in `openpiv/test/conftest.py` disable plotting for CI -- Sample data includes real PIV image pairs for testing workflows +- Uses stdlib `importlib.resources.files()` (NOT the third-party `importlib_resources`) to locate bundled data +- Test configurations in `openpiv/test/conftest.py` disable matplotlib GUI (uses `Agg` backend, patches `plt.show`) +- Sample data bundled at `openpiv/data/test1/`; accessed via `files('openpiv.data').joinpath('test1/...')` +- `pyproject.toml` still uses the deprecated `[tool.poetry.dev-dependencies]` section; this generates a warning but is harmless - Documentation built with Sphinx (source in `openpiv/docs/`) - External examples repository: [OpenPIV-Python-Examples](https://github.com/OpenPIV/openpiv-python-examples) ### Common Command Reference ```bash # Development setup -poetry install # ~10 seconds -poetry run pytest openpiv -v # ~12 seconds, 198 tests pass +poetry install # ~10 seconds +poetry run pytest openpiv -v # ~10 seconds, 216 tests pass -# Testing functionality -poetry run python openpiv/tutorials/tutorial1.py # Complete PIV workflow -poetry run python -c "import openpiv.piv as piv; ..." # API test +# Testing functionality +poetry run python openpiv/tutorials/tutorial1.py # Complete PIV workflow +poetry run python -c "import openpiv.piv as piv; ..." # API test # Alternative installs -pip install openpiv # ~33 seconds -conda install -c conda-forge openpiv # ~46 seconds +pip install openpiv # ~33 seconds +conda install -c conda-forge openpiv # ~46 seconds # Build from source (minimal - no Cython compilation needed) -python setup.py build_ext --inplace # <1 second +python setup.py build_ext --inplace # <1 second ``` ### Timing Expectations and Timeouts - **Poetry install**: ~10 seconds (set 5+ minute timeout) -- **Test suite**: ~12 seconds (set 30+ minute timeout for safety) -- **Tutorial execution**: ~1-2 seconds +- **Test suite**: ~10 seconds (set 30+ minute timeout for safety) +- **Tutorial execution**: ~1-2 seconds - **Pip install**: ~33 seconds (set 10+ minute timeout) - **Conda install**: ~46 seconds (set 15+ minute timeout) - **Build from source**: <1 second (no Cython compilation currently) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 00000000..9b79d8c0 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,34 @@ +name: "Copilot Setup Steps" + +# Run automatically when this file changes, and allow manual runs from the Actions tab. +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # Job name MUST be `copilot-setup-steps` to be picked up by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Poetry + run: pip install poetry + + - name: Install project dependencies + run: poetry install From 77f96dca07c7a28eb71c66bf09caaf78a5d66b1c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 19:50:58 +0000 Subject: [PATCH 2/2] chore: clarify Cython removal in copilot-instructions.md Agent-Logs-Url: https://github.com/OpenPIV/openpiv-python/sessions/3fb231b9-1ebc-422f-bb3b-26c6a589a7ed Co-authored-by: alexlib <747110+alexlib@users.noreply.github.com> --- .github/copilot-instructions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6167177c..8b498e20 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -105,6 +105,7 @@ s.num_iterations = 3 - **Key dependencies**: numpy ≥2.0, scipy ≥1.11, scikit-image ≥0.23, matplotlib ≥3.8, imageio ≥2.35, natsort, tqdm ### Development Notes +- **No Cython extensions**: Although the package description still mentions "Cython modules" (legacy), all Cython (`.pyx`) files have been removed and converted to pure Python. `python setup.py build_ext --inplace` takes <1 second with nothing to compile. - Uses stdlib `importlib.resources.files()` (NOT the third-party `importlib_resources`) to locate bundled data - Test configurations in `openpiv/test/conftest.py` disable matplotlib GUI (uses `Agg` backend, patches `plt.show`) - Sample data bundled at `openpiv/data/test1/`; accessed via `files('openpiv.data').joinpath('test1/...')`