Skip to content

VBPCApy 0.4.11 validation

This patch corrects sparse covariance sharing: samples with matching observed feature rows are grouped by their sample-column indices. The earlier grouping could update the wrong columns and fail rotation's coverage check. The repair retains sparse storage, first-seen pattern IDs and explicitly stored zeros.

Modern sparse fits also retain observed zeros in noise-update coordinates, probe exclusion and NaN cleanup. Previously, a stored zero could disappear from the fitted observation set and change noise estimates or later updates. Strict-legacy coordinate, normalization and probe behavior is retained. Record the chosen compatibility mode when comparing software versions.

The release also adds typed result and learning-curve mappings with executable docstring examples. Existing result keys and array ownership are preserved. Learning-curve types distinguish numeric histories from iteration indices, reason strings, patience counts and prior vectors. Accurate static types may require callers' generic mutable dictionary annotations to become PCAResult or a read-only Mapping[str, object]; runtime values remain ordinary dictionaries. See the result reference.

From the release checkout:

uv sync --extra dev --extra plot --extra docs
uv run python scripts/check_release_metadata.py --tag v0.4.11
just ci
uv run pytest -q tests/test_sparse_pattern_groups.py tests/test_sparse_observed_zero_indices.py tests/test_result_contracts.py
uv run --extra docs mkdocs build --strict
just build-check
just build-test

The sparse regressions check exact sample coverage, absence of mask densification and unchanged caller inputs. Shared and unshared fits are compared across VB/PPCA/MAP, both compatibility modes, Python/bulk covariance writeback, both sharing options and one/two/four native threads. They compare reconstructions, noise, RMS, costs and uncertainty with relative tolerance 1e-9 and absolute tolerance 1e-10. A consistent component-sign alignment is applied to factors and covariance blocks because eigenvectors can differ in sign without changing the model.

Observed-zero checks compare dense and sparse fits with bias enabled/disabled, complete/masked observations, covariance sharing, zero/nonzero probes and stored NaNs. They also exercise CSR filtering with empty rows/storage, read-only inputs and independent output ownership. The standalone 63-entry reproducer now retains all 63 noise coordinates and matches its dense fit.

Result tests exercise dense/sparse data, observed zeros, diagnostic options, covariance representations, package-root exports, runtime type-hint resolution and checked consumer examples. The normal test suite executes the public docstring examples and verifies rejection of invalid keys/metadata by mypy. Clean wheel-test environments include that checker. CI also checks source and consumer types with the pinned NumPy 2.4/SciPy stub versions for Linux, macOS and Windows targets. Dense and sparse index arrays can have different intermediate widths; both retain the same intp outputs.

The publishing workflow must build and test all twelve advertised wheels and the source archive, then pass artifact completeness checks before PyPI upload. Keep its receipts separate from local source tests. The independent numerical references remain required; these bounded checks do not establish scientific calibration or convergence. Update equations and stopping defaults are unchanged. Frozen study environments stay pinned pending a recorded adoption.