diff --git a/config/general.yaml b/config/general.yaml index 6ca1941..8d3bae6 100644 --- a/config/general.yaml +++ b/config/general.yaml @@ -1,6 +1,8 @@ updates: iterations_per_quick_update: 1e99 # Non-linear search iterations between every quick update, which just displays the maximum likelihood model fit. iterations_per_full_update: 1e99 # Non-linear search iterations between every full update, which outputs all visuals and result fits (e.g. model.result, search.summary), this exits the search and can be slow. + quick_update_background: false # If True, perform_quick_update runs on a background daemon thread so the sampler is never blocked while visuals render. Requires the Analysis subclass to set `supports_background_update = True`. + live_visual_update: false # If True, quick-update visuals are pushed to a live surface (a Jupyter cell when in a kernel, a matplotlib viewer subprocess otherwise) in addition to being written to disk. fits: flip_for_ds9: true psf: @@ -18,6 +20,8 @@ hpc: hpc_mode: false # If True, use HPC mode, which disables GUI visualization, logging to screen and other settings which are not suited to running on a super computer. iterations_per_quick_update: 250000 # Non-linear search iterations between every quick update, which just displays the maximum likelihood model fit. iterations_per_full_update: 1e99 # Non-linear search iterations between every full update, which outputs all visuals and result fits (e.g. model.result, search.summary), this exits the search and can be slow. + quick_update_background: false # Keep off on HPC: background rendering pulls matplotlib into the sampler process even when no display is attached. + live_visual_update: false # Keep off on HPC: nodes are headless with no GUI and no notebook kernel, so the live display surface has nothing to attach to. adapt: adapt_minimum_percent: 0.01 adapt_noise_limit: 100000000.0 diff --git a/skills/al_configure_search.md b/skills/al_configure_search.md index 82efba5..63117fb 100644 --- a/skills/al_configure_search.md +++ b/skills/al_configure_search.md @@ -93,6 +93,33 @@ Zeus (ensemble slice MCMC), DynestyDynamic (dynamic nested sampling), BFGS / LBF (gradient descent for MLE), Drawer (random prior draws — debugging only). See [`wiki/core/api/searches.md`](../wiki/core/api/searches.md) for the comparison table. +## Branch — Live visual updates + +When configuring an **interactive production fit** (foreground script or notebook), ask once: +*watch the fit update live?* The quick-update image (`fit.png`) is **always written to disk** +every `iterations_per_quick_update` iterations regardless; `live_visual_update=True` (default +`False`) additionally pushes it to a live display surface: + +- **foreground Python script** — a matplotlib viewer opens and refreshes with each quick + update; +- **Jupyter / Colab** — the cell that ran `search.fit(...)` refreshes one image in place; +- **HPC, headless, background, or unattended runs** — keep it `False` (nothing to attach to; + HPC mode disables it in config). + +```python +search = af.Nautilus( + ..., + iterations_per_quick_update=1000, # quick-update (and live refresh) cadence + live_visual_update=True, # script: matplotlib viewer; notebook: in-place cell +) +``` + +Both are shared search options (accepted by every search via the common base class), with +config fallbacks in `config/general.yaml` `updates:`. Don't re-ask on later runs — the +choice is recorded in the search configuration. + +Source: `PyAutoFit:autofit/non_linear/search/abstract_search.py`. + ## Output folder layout After `search.fit(...)` runs, results land at: diff --git a/skills/al_run_search.md b/skills/al_run_search.md index 095b141..b482a62 100644 --- a/skills/al_run_search.md +++ b/skills/al_run_search.md @@ -24,6 +24,12 @@ in `PYAUTO_TEST_MODE=1` for a smoke test or in production mode for the real fit. ## Branch — production run +Operational reminder: if the search was configured with `live_visual_update=True` +(`al_configure_search` "Live visual updates"), a foreground script opens a matplotlib viewer +and a notebook cell refreshes in place — don't re-ask when the search configuration already +records the choice, and keep it `False` for HPC/headless/background runs. `fit.png` is +written to disk on every quick update either way. + Assemble everything into one script (`scripts/run_fit.py`): ```python diff --git a/wiki/core/api/searches.md b/wiki/core/api/searches.md index 0e269a7..b11b61e 100644 --- a/wiki/core/api/searches.md +++ b/wiki/core/api/searches.md @@ -159,7 +159,14 @@ Every search accepts: - `unique_tag: Optional[str]` — extra discriminator for runs that share path + name. - `number_of_cores: int` — parallel likelihood evals. - `iterations_per_quick_update: int` / `iterations_per_full_update: int` — checkpoint - cadence (quick intermediate writes vs full output + visualisation). + cadence (quick intermediate writes, incl. the max-likelihood `fit.png`, vs full output + + visualisation). Config fallbacks in `general.yaml` `updates:` (HPC mode overrides under + `hpc:`). +- `live_visual_update: bool` — default `False`; if `True`, each quick update is also pushed + to a live display surface (matplotlib viewer from a foreground script, in-place cell + refresh in Jupyter/Colab) in addition to the unconditional disk write. Keep `False` on + HPC/headless/background runs. Accepted by every search (common base class); reaches + `af.Nautilus(...)` via `**kwargs`. - `silence: bool` — suppress console output. See `PyAutoFit:autofit/non_linear/search/abstract_search.py` for the common base