Found while reviewing #376.
The Cluster Strength control is built on the assumption that the number in the spinner is the number the map was clustered with. For a large album that is not true, and nothing in the response says so.
resolve_cluster_eps applies _shrink_eps_to_pair_budget to every value, typed or derived (photomap/backend/cluster_eps.py:218) — deliberately, since it is a memory bound rather than a quality opinion, and the docstring says as much. But the shrunk number is used and discarded: /umap_data returns points and cluster ids, never the eps it resolved. So the UI goes on displaying what the user typed.
Measured on a synthetic cloud the size of a real album (random normal, 2-D, span ~33 units — MAX_NEIGHBOR_PAIRS is 50,000,000, so the shrink engages once n is in the tens of thousands):
| images |
typed & stored |
map actually clustered at |
| 20,000 |
3.0 |
2.100 |
| 40,000 |
2.0 |
1.400 |
| 40,000 |
3.0 |
1.029 |
3.0 is the spinner's own max, i.e. a value the control invites by holding the up-arrow.
End state for a 40k-image album tuned to 2.0: the spinner shows 2, /get_umap_eps returns 2 with auto: false, the cluster-info modal reports 2.00 — and the blobs on screen are the ones you get at 1.4. Re-tuning is guesswork, because the control's feedback is decoupled from its effect above the budget.
Note this cannot be fixed on the client. The threshold depends on the point cloud, not on any bound expressible in the markup — #376 enforces the spinner's min for exactly the same class of divergence at the bottom end (where the server floors to MIN_CLUSTER_EPS), but there is no equivalent static ceiling.
Suggested fix
Have /umap_data (and /cluster_labels, which resolves through the same helper) return the eps it actually clustered with, and have the frontend show that rather than what was typed — the same shape as /get_umap_eps's existing {eps, auto}. The spinner keeps the user's number as the request; the display, the "auto" badge and the cluster-info modal report what was used. That also gives #381 a source of truth to read.
Found while reviewing #376.
The Cluster Strength control is built on the assumption that the number in the spinner is the number the map was clustered with. For a large album that is not true, and nothing in the response says so.
resolve_cluster_epsapplies_shrink_eps_to_pair_budgetto every value, typed or derived (photomap/backend/cluster_eps.py:218) — deliberately, since it is a memory bound rather than a quality opinion, and the docstring says as much. But the shrunk number is used and discarded:/umap_datareturns points and cluster ids, never the eps it resolved. So the UI goes on displaying what the user typed.Measured on a synthetic cloud the size of a real album (random normal, 2-D, span ~33 units —
MAX_NEIGHBOR_PAIRSis 50,000,000, so the shrink engages oncenis in the tens of thousands):3.0is the spinner's ownmax, i.e. a value the control invites by holding the up-arrow.End state for a 40k-image album tuned to 2.0: the spinner shows
2,/get_umap_epsreturns2withauto: false, the cluster-info modal reports2.00— and the blobs on screen are the ones you get at 1.4. Re-tuning is guesswork, because the control's feedback is decoupled from its effect above the budget.Note this cannot be fixed on the client. The threshold depends on the point cloud, not on any bound expressible in the markup — #376 enforces the spinner's
minfor exactly the same class of divergence at the bottom end (where the server floors toMIN_CLUSTER_EPS), but there is no equivalent static ceiling.Suggested fix
Have
/umap_data(and/cluster_labels, which resolves through the same helper) return the eps it actually clustered with, and have the frontend show that rather than what was typed — the same shape as/get_umap_eps's existing{eps, auto}. The spinner keeps the user's number as the request; the display, the "auto" badge and the cluster-info modal report what was used. That also gives #381 a source of truth to read.