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 campaigns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ campaigns:
title: Interferometer likelihood and streaming
status: active
updated: '2026-10-15'
next: 'All three PyAutoArray members from the Aris 512×512 profiling (PyAutoPulse#62) merged 2026-10-15, pending release: #630 sparse data vector memory, #631 AdaptSplit log-det backend parity, #632 numba route-gate cost model; phase-2 autolens_profiling record in flight. Streaming 1e8 CPU/A100 rows and the #332 memo after-measurement still need authorization; curvature preload needs the fixed-mapper science decision; FFT levers remain unstarted.'
next: 'Aris large-mask work (PyAutoPulse#62): #630/#631/#632 merged 2026-10-15, pending release; knowledge section and two human decisions recorded; phase-2 record at PR-open (autolens_profiling#420); L1 Cholesky reuse (PyAutoArray#633) in development, L2 direct_conv symmetry filed and unstarted. Streaming 1e8 CPU/A100 rows and the #332 memo after-measurement still need authorization; curvature preload needs the fixed-mapper science decision; FFT levers remain unstarted.'
evidence: https://github.com/PyAutoLabs/autolens_profiling/blob/4db4d988e520a82219152743748c3188d485a4ba/wiki/campaigns/interferometer_likelihood.md
- id: linear-solver
title: Linear-solver accuracy and cost
Expand Down Expand Up @@ -307,7 +307,7 @@ tasks:
priority: high
path: tasks/interferometer_large_mask_aris.md
updated: '2026-10-15'
next: 'All three library members merged (PRs #630, #631, #632; pending release). In flight: autolens_profiling phase-2 record (routing table under the cost model + Aris log-det after-measurement). Then copy that table here and close the task.'
next: 'Knowledge written 2026-10-15 (cost structure, routing model, levers, collaborator settings) and the two human decisions recorded. #630/#631/#632 merged, pending release. Phase-2 record at PR-open (autolens_profiling#420): re-pin its table on merge. L1 Cholesky reuse (PyAutoArray#633) in development; L2 direct_conv symmetry filed, unstarted.'
issue: https://github.com/PyAutoLabs/PyAutoPulse/issues/62
evidence: https://github.com/PyAutoLabs/PyAutoArray/issues/626
- id: interferometer_w_tilde_fft_size_levers
Expand Down
2 changes: 1 addition & 1 deletion dashboard.html

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions dashboard.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PyAutoPulse — profiling dashboard

<!-- pulse-campaigns:0ec1ffed93e62a62d70397b0e88007eb2e1d8284d3e4f54f10d7c51896a2ac7e -->
<!-- pulse-campaigns:4e132b2d2378f34b9712646cb9a497b82be62a3d7d484f8136ab2bc19cc70303 -->
## Profiling Check In

<details><summary>Full check-in prompt</summary>
Expand Down Expand Up @@ -94,7 +94,7 @@ Reviewed 2026-10-13. No campaign wiki/results change or new matching implementat

<details><summary>Interferometer likelihood and streaming — active</summary>

Reviewed 2026-10-15. All three PyAutoArray members from the Aris 512×512 profiling (PyAutoPulse#62) merged 2026-10-15, pending release: #630 sparse data vector memory, #631 AdaptSplit log-det backend parity, #632 numba route-gate cost model; phase-2 autolens_profiling record in flight. Streaming 1e8 CPU/A100 rows and the #332 memo after-measurement still need authorization; curvature preload needs the fixed-mapper science decision; FFT levers remain unstarted.
Reviewed 2026-10-15. Aris large-mask work (PyAutoPulse#62): #630/#631/#632 merged 2026-10-15, pending release; knowledge section and two human decisions recorded; phase-2 record at PR-open (autolens_profiling#420); L1 Cholesky reuse (PyAutoArray#633) in development, L2 direct_conv symmetry filed and unstarted. Streaming 1e8 CPU/A100 rows and the #332 memo after-measurement still need authorization; curvature preload needs the fixed-mapper science decision; FFT levers remain unstarted.

[Campaign evidence](https://github.com/PyAutoLabs/autolens_profiling/blob/4db4d988e520a82219152743748c3188d485a4ba/wiki/campaigns/interferometer_likelihood.md)

Expand All @@ -103,7 +103,7 @@ Reviewed 2026-10-15. All three PyAutoArray members from the Aris 512×512 profil
- [Interferometer fixed-mapper searches: reuse the W~ curvature matrix across likelihood calls via `preloads.curvature_matrix`](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_fixed_mapper_curvature_preload.md) — ready: Phase 1 Mind draft (2026-10-04) still unstarted; run it through start_dev. Human science call first - no production SLaM stage holds the mapper fixed today.
- [fnnls warm-start memo: stop it slowing scattered evaluation streams (interferometer CPU, autolens_profiling#332)](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_nnls_memo_scattered_stream_guard.md) — active: Library half shipped: PyAutoArray#615 (closes #613) merged 2026-10-06, in 2026.10.7.1. Local solver-only witness (n=576): iid memo on/off 1.49x → 1.17x; walk 0.18x unchanged. Owed: re-run the autolens_profiling#332 ALMA Delaunay 2.17x after-measurement (needs compute authorization).
- [Campaign: interferometer streaming (array-free) vs in-memory — memory and time scaling to 2e8 visibilities](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_streaming_scaling.md) — active: Phase 1 CPU cells + results/streaming_scaling rows merged (autolens_profiling#375, 2026-10-04); wiki/campaigns/interferometer_streaming.md. Optional: 1e8 CPU row and A100 rows (compute authorization). Library candidate unfiled: chunk transformer.image_from in apply_sparse_operator (memory).
- [Interferometer large-mask likelihood (Aris 512×512): sparse data-vector memory, AdaptSplit log-det backend parity, numba route-gate cost model](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_large_mask_aris.md) — active: All three library members merged (PRs #630, #631, #632; pending release). In flight: autolens_profiling phase-2 record (routing table under the cost model + Aris log-det after-measurement). Then copy that table here and close the task.
- [Interferometer large-mask likelihood (Aris 512×512): sparse data-vector memory, AdaptSplit log-det backend parity, numba route-gate cost model](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_large_mask_aris.md) — active: Knowledge written 2026-10-15 (cost structure, routing model, levers, collaborator settings) and the two human decisions recorded. #630/#631/#632 merged, pending release. Phase-2 record at PR-open (autolens_profiling#420): re-pin its table on merge. L1 Cholesky reuse (PyAutoArray#633) in development; L2 direct_conv symmetry filed, unstarted.
- [Interferometer W~ curvature matrix is FFT-bound on the mask extent: pruned padded FFT and real-space pixel scale on the A100](https://github.com/PyAutoLabs/PyAutoPulse/blob/main/tasks/interferometer_w_tilde_fft_size_levers.md) — ready: Unstarted (no PR/issue/branch/results, 2026-10-04). Select one bounded step when prioritised.

</details>
Expand Down Expand Up @@ -330,7 +330,9 @@ Project `autofit_profiling`, scope `pyautofit-profiling`, read from [PyAutoLabs/
</details>


<!-- decision-history:8f1840916151d6a62b1cb1cd473edede0a3647c198fe8ef2371ce31a66c873a5 -->
<!-- decision-history:20f0256fc1d56eda82a910f81ddb71d393e76eeaf26e486d9c836b00282b99f9 -->
## Decision History

- <a href="https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/interferometer-route-gate-cost-model.md">Route interferometer curvature by a calibrated two-constant cost model</a>
- <a href="https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/adaptsplit-zero-weight-delaunay-only.md">Exclude zero-weight mappings from AdaptSplit pixel signals on Delaunay meshes only</a>
- <a href="https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/linear-solver-mapper-default-jacobi.md">Keep Jacobi PDIP as the Mapper default and raw+polish as the MGE-only default</a>
8 changes: 8 additions & 0 deletions decisions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ decisions:
title: Keep Jacobi PDIP as the Mapper default and raw+polish as the MGE-only default
date: '2026-10-08'
url: https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/linear-solver-mapper-default-jacobi.md
- id: adaptsplit-zero-weight-delaunay-only
title: Exclude zero-weight mappings from AdaptSplit pixel signals on Delaunay meshes only
date: '2026-10-15'
url: https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/adaptsplit-zero-weight-delaunay-only.md
- id: interferometer-route-gate-cost-model
title: Route interferometer curvature by a calibrated two-constant cost model
date: '2026-10-15'
url: https://github.com/PyAutoLabs/PyAutoPulse/blob/main/decisions/interferometer-route-gate-cost-model.md
113 changes: 113 additions & 0 deletions decisions/adaptsplit-zero-weight-delaunay-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Exclude zero-weight mappings from AdaptSplit pixel signals on Delaunay meshes only

Date: 2026-10-15
Decision maker: James Nightingale
Decision source: AskUserQuestion answer "Delaunay only (Recommended by review)" in session 3e3dea38, 2026-10-15. Quoted on [PyAutoArray#627 (issuecomment-6200058449)](https://github.com/PyAutoLabs/PyAutoArray/issues/627#issuecomment-6200058449). Recorded on the human's explicit direction in the same session ("Yes, record it as my decision").

## Campaign

This decision belongs to the interferometer campaign, task `interferometer_large_mask_aris`
([PyAutoPulse#62](https://github.com/PyAutoLabs/PyAutoPulse/issues/62)). The task profiles the Aris
SPT2319-55 interferometer setup: a Delaunay mesh with `AdaptSplit` regularization, on real-space
masks of 125×125 (5,496 px) and 512×512 (91,507 px), with 5.5M visibilities.

The numba/NumPy and JAX backends returned different log evidences at identical parameters. The whole
difference was in `log_det_regularization_matrix_term`: 2443.22 on numba against 2561.98 on JAX for
one 125×125 vector. Evidences were therefore not comparable across backends or across pipeline phases
that mix them. The issue was
[PyAutoArray#627](https://github.com/PyAutoLabs/PyAutoArray/issues/627).

## Evidence

The evidence is at PyAutoArray `ccddfba6` (before the fix) and `0377eeaa` (the merge of
[#631](https://github.com/PyAutoLabs/PyAutoArray/pull/631)), on the laptop in fp64. It is drawn from
the #627 comments "Root cause found" (issuecomment-6197915508) and "Parked at the review leg"
(issuecomment-6199913182), and from Mind `complete/2026/10/adaptsplit-logdet-backend-parity.md`.

- **The factorizations were not the cause.**
- On each backend's own H, five methods agree with a 50-digit mpmath reference to ≤ 2e-8: NumPy
dense Cholesky, SuperLU, JAX Cholesky, slogdet and diagonal scaling.
- The two backends built different H matrices: max |H_np − H_jax| = 3.21, on max |H| 31.9.
- **Root cause.**
- `adaptive_pixel_signals_from` divided each pixel's summed signal by a count that included
zero-weight mapping entries.
- The 125×125 mesh is a stride-2 subsample of the data grid, so 1,375 data points sit exactly on
vertices. For such a point any surrounding triangle is valid.
- scipy `find_simplex` and the JAX Delaunay walk chose different triangles in 1,114 of 5,496 rows.
Both choices are geometrically correct.
- The phantom zero-weight neighbours changed the counts, then the pixel signals (max diff 0.23),
the AdaptSplit weights (0.53) and H.
- Chi², the curvature matrix, the data vector and the curvature log det were unaffected.
- **Simulated fix: count only non-zero weights.** Signals agree to 4e-15 and H to 4.8e-13. The log
det is 2468.446318 on both backends (Δ 4e-8).
- **Review finding on the first patch, which applied the rule to every interpolator.**
- `KNNBarycentric` clips negative barycentric weights to exactly 0 for every query outside its
3-nearest triangle, so whole regions are affected, not only coincident points.
- Excluding those zeros would change its pixel signals and evidence broadly.
- It would also add a jump in the likelihood: moving one weight from 1e-9 to 0 moved a test scalar
from 6.2358 to 6.4889, and the gradient at w = 0 is exactly 0.
- Rectangular bilinear meshes are affected only in exact-coincidence cases.
- **Shipped result (#631, Delaunay-only scope).**
- On a synthetic ill-conditioned AdaptSplit case (cond ≈ 2.2e9), H parity is 3.6e-15 and the
log dets are 2.1e-9 apart, both within 1.7e-9 of a 50-digit reference.
- The independent re-review found KNN, KNNBarycentric and rectangular bit-identical to main.
- **After-measurement on the Aris data.**
- Source: [autolens_profiling#420](https://github.com/PyAutoLabs/autolens_profiling/pull/420), head
`32372865`, **at PR-open, not merged**, on PyAutoArray `17caf228`.
- numba and JAX agree to ≤ 4.4e-8 at all six cells (125: 1,405/2,947/5,526 vertices; 512:
1,459/2,577/5,746).
- The original 125×125 vector gives 2468.4463180 on both backends.
- **Limitation: a residual remains.** The split regularization builders add an absolute 1e-8 diagonal
jitter. Once max(coeff)^4 ≳ 1e6, the log det is round-off-dominated (cond 1e16–1e17).
- In 20 prior draws on 125×125 with the counting fix, 6 still differed by 5e-3–2.2.
- This decision does not address the residual, and no work on it is filed.

## Options considered

- **(a) Accept the rule for every mesh, including KNN and KNNBarycentric.** This is the simplest
code. But KNNBarycentric evidence would change across whole regions, and its likelihood would gain
a discontinuity on a mesh used for gradient-based fits.
- **(b) Delaunay only** (chosen; recommended by the independent review). Exclude zero-weight mappings
for Delaunay and DelaunayNN, and keep the old counting elsewhere. It fixes the parity bug where it
arises, at the cost of one keyword and one interpolator class attribute.
- **(c) Weight-normalised signals.** Divide the summed signal by the summed weights rather than by a
count, so zero weights drop out on every mesh without a jump. This was raised in the session as
the route if KNN-family parity is ever needed. It was not prototyped or measured.
- The #627 park comment listed a different third option: make the scipy/JAX triangle choice
deterministic for coincident points and keep the count semantics. That option had been rejected
earlier in the investigation.

## Decision

Exclude zero-weight mapping entries from the adaptive pixel-signal counts for Delaunay and
DelaunayNN interpolators only. KNN, KNNBarycentric and rectangular meshes keep the previous counting.

## Implications

- **Shipped in [#631](https://github.com/PyAutoLabs/PyAutoArray/pull/631)** (merge `0377eeaa`,
pending release).
- `adaptive_pixel_signals_from(..., exclude_zero_weight_mappings=False)` gains a keyword.
- It is driven by the interpolator class attribute `exclude_zero_weight_mappings`: True on
InterpolatorDelaunay and InterpolatorDelaunayNN, False on the base interpolator and KNN.
- **Evidence values change, the same way on both backends,** on Delaunay and DelaunayNN meshes where
data points sit exactly on vertices or edges, for example Overlay or grid-subsample image meshes.
Any pinned evidence for such a mesh will shift. No smoke script failed (151/151), and no workspace
change was needed.
- **KNN, KNNBarycentric and rectangular meshes are bit-identical** to the previous release.
- numba/JAX evidences on Delaunay AdaptSplit fits are now comparable to ~1e-8 at moderate
coefficients. The high-coefficient jitter regime is still backend-sensitive.

## Revisit conditions

- **KNN-family parity is needed,** for example a KNNBarycentric backend-parity requirement. Then
evaluate weight-normalised signals (option c), which avoids the discontinuity of option (a).
- **The jitter residual matters in practice.** That is, fits reach max(coeff)^4 ≳ 1e6, or the 512×512
non-PD rate (~1 in 4 draws before #631) is still seen. A relative jitter
(`1e-8 * max(regularization_weights**2)`) is the candidate. It changes evidence values, so it needs
its own decision.
- **A change to the Delaunay point-location routines,** in scipy or the JAX walk, or a new
interpolator whose weights can be exactly zero.

## History

This is the first decision on this question. It supersedes nothing.
Loading
Loading