Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ NumPy 2.5.4 pins cover lengths 1, 2, 4, 8, 64, 256 and 1024. The tests state the
```text
// Package.swift
dependencies: [
.package(url: "https://github.com/mac4DSTEM/ImagoKit.git", exact: "0.8.0"),
.package(url: "https://github.com/mac4DSTEM/ImagoKit.git", from: "0.8.0"),
],
targets: [
.target(name: "MyApp", dependencies: [
Expand Down Expand Up @@ -196,7 +196,7 @@ reference within its own tolerance; `docs/parity.md` lists each function, its st
- iOS 18 builds but has never been run on a device or simulator; macOS 15 is declared but built and tested on macOS 27 only.
- A first call of a vDSP 1D FFT or DFT size can differ by one Float32 ulp.
- Float32 tolerances are claims on the planted and pinned cases, not proofs for every input.
- Zoom and rotate refuse the `wrap` mode at spline orders 2 to 5; the masked registration returns the shift only, and a symmetric pair with exactly tied maxima is not reproducible (`docs/open-items.md`).
- Zoom and rotate refuse the `wrap` mode at spline orders 2 to 5; the masked registration returns the shift only, and a symmetric pair with exactly tied maxima is not reproducible (`docs/parity.md`, known limits).
- No number is validated on a microscope; the HRTEM filters have never been compared with DigitalMicrograph.
- Not yet checked on a raw (counts) HRTEM image; the available TIFFs are 8-bit renders.

Expand Down
4 changes: 2 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Roadmap

ImagoKit is pre-1.0: a minor version may change the API, and its CHANGELOG entry says how to migrate. The detailed list of
gaps is [`docs/open-items.md`](docs/open-items.md); the function-by-function state is [`docs/parity.md`](docs/parity.md).
ImagoKit is pre-1.0: a minor version may change the API, and its CHANGELOG entry says how to migrate. Open work is in the GitHub
issues; the function-by-function state and the known limits are in [`docs/parity.md`](docs/parity.md).

## Next

Expand Down
39 changes: 0 additions & 39 deletions docs/open-items.md

This file was deleted.

22 changes: 22 additions & 0 deletions docs/parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,25 @@ Numerics are never held stricter than that; readers, I/O, indices and metadata a
| Function or option group | State | Kit symbol | Counterpart tolerance (source) | Priority | Notes |
|---|---|---|---|---|---|
| GPA strain from two reflections of a lattice image (Hytch, Snoeck and Kilaas 1998) | present, validation none (0.8.0) | `GeometricPhaseAnalysis.analyze`, `findReflections` | the planted field of `tools/gpa/planted.py` (no upstream package): 2x the plain-numpy selfcheck error per case (uniform 9.8e-4, bump 3.12e-3, bump_oblique 2.97e-3, perfect 1e-6), floor 1e-6, interior only | study | Float64 CPU only; measured errors equal the numpy GPA's (4.89e-4, 1.56e-3, 1.48e-3, 2.5e-11 at size 128); badged `validation: "none"` until one dataset with truth passes |

## Known limits and decisions

Open work is in the [issues](https://github.com/mac4DSTEM/ImagoKit/issues), including the ones closed as *not planned* and
parked for later (`label` speed #6, upsampled registration #7, FFT gaps #8, 1.0 naming #9, precipitation benchmarks #11).
Speed against Python is in `docs/benchmarks.md`.

- **`fft2` Float64 on the vDSP lengths** (2^n x {3, 5, 15}) is up to 1.12x NumPy (480²: 1.53 ms against 1.37); the remainder
is the transposes around the vDSP calls. The kit keeps the vDSP path by design.
- **Naming before 1.0:** the newer surface takes `rows`/`columns`; `LabelImage`, `Micrograph` and the older morphology and
segmentation API still say `width`/`height` (unified at 1.0, a break).
- **`BinaryMorphology`** refuses even structures and an all-false structure (SciPy shifts the origin and answers) and runs a
per-pixel loop (fine at 512², slow for a 4096² mask).
- **`Thresholding.yen`** can differ from scikit-image on an image of more than 2^24 pixels whose last histogram bin is nearly
empty (Float32 `P1` reaches 1 and NumPy's `argmax` returns the first NaN).
- **`regionProperties`** computes every property per object; use `objectMoments` alone for just the moments.
- **`zoom` and `rotate` with `wrap`** at spline orders 2 to 5 are refused by name; the shifts measured the rule (prefilter
and taps as `mirror`, the coordinate mapped with period n − 1), the resampling coordinate path has not been checked against it.
- **Masked registration:** scikit-image's `xcorr == xcorr.max()` tie rule is reproducible only for a unique maximum; the
kit's fast length is the next 7-smooth length, SciPy's also allows 11, so symmetric pairs decide on rounding noise.
- **Metal Float32 paths** (FFT, then the separable filters) are not written; the break-even at 2048² to 8192² is measured in
the nightly review first.
2 changes: 1 addition & 1 deletion docs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
ImagoKit 0.8.0 (2026-10-22), against NumPy 2.5.4, SciPy 1.18.1 and scikit-image 0.26.0. Live: the FFT surface (`fft2`, `rfft2`, `fftshift`, axes and norm), power spectra and
spot measurement, Gaussian, uniform, difference-of-Gaussians, Butterworth and window filters, Fourier and spline-order shifts, phase correlation (plain and masked), HRTEM filter
steps, `peak_local_max`, profiles, colormaps, segmentation helpers (thresholds, binary morphology, labelled statistics, `regionprops` completion, areal density, distance transform, watershed, rolling ball), zoom and rotate, TV and non-local-means denoising, real-input 2D and 1D transforms and a mixed-radix Float64 plan, GPA strain (planted truth, validation none), CSV export. Parity: `docs/parity.md` (93 rows: 36 present, 12 partial, 45 missing); timings against Python:
`docs/benchmarks.md`; what is open (the upsampled registration, `label`, Metal paths): `docs/open-items.md`.
`docs/benchmarks.md`; what is open: the GitHub issues (the upsampled registration, `label`, Metal paths); known limits: `docs/parity.md`.

Test split: the comparisons with the pinned NumPy, SciPy and scikit-image values and the benchmark harness are the `ImagoKitParityTests` target (fixtures stay in `Tests/Imago*Tests/Fixtures`, found through `ImagoKitTestSupport`); `swift test -c release --parallel --skip ImagoKitParityTests` runs the fast unit tests (what every pull request runs), the plain `swift test -c release --parallel` the full suite (before a release and nightly). On an Apple Silicon Mac, release, warm build, the fast target takes about 2 s and the full suite about 5 s.
Loading