Overview
Users regularly complain about the default colormap. The lever to change it already exists — PyAutoArray/autoarray/plot/utils.py::_default_colormap() reads visualize/general.yaml → colormap and every 2D plot function takes a colormap argument — but it is undocumented, and the config read is wrapped in a bare except Exception so a typo'd key or an unknown colormap name silently reverts to the bundled autoarray map with no warning. This task audits the lever end-to-end, makes malformed values loud, documents the two override routes, and defaults the Euclid pipeline repo to magma.
Phase 0 of 10 in the euclid-dr1-prep epic. Independent of every other phase — it gates nothing and nothing gates it.
Plan
- Audit that the
colormap config key actually reaches every 2D plotting surface across PyAutoArray / PyAutoGalaxy / PyAutoLens, and document the deliberate exceptions (hardcoded, semantically-chosen colormaps) rather than leaving them silent.
- Make
_default_colormap() loud: an absent config still falls back quietly to autoarray, but a present but unresolvable colormap name raises a clear ValueError naming the config key and the bad value. Replace the bare except Exception with a narrow one.
- Verify and document the per-figure override route through the public plot API (
colormap= on every plot_* entry point).
- Add a "Changing the colormap" section to the
config/visualize/README.md files (PyAutoArray + the Euclid pipeline repo).
- Set
colormap: magma in euclid_strong_lens_modeling_pipeline/config/visualize/general.yaml. Leave PyAutoArray and autolens_workspace on autoarray.
Detailed implementation plan
Affected Repositories
- PyAutoArray (primary — library)
- euclid_strong_lens_modeling_pipeline (workspace follow-up)
PyAutoLens / PyAutoGalaxy are audited but not edited — their plot surfaces already thread colormap down to autoarray's plot_array / plot_grid / plot_mapper.
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoArray |
main |
clean |
| ./PyAutoLens |
main |
clean |
| ./autolens_workspace |
main |
clean |
| ./euclid_strong_lens_modeling_pipeline |
main |
clean |
worktree_check_conflict cmap-magma-default PyAutoArray euclid_strong_lens_modeling_pipeline → no conflict.
Suggested branch: feature/cmap-magma-default
The lever as it stands (surveyed 2026-08-28)
# PyAutoArray/autoarray/plot/utils.py
def _default_colormap() -> str:
try:
from autonerves import conf
name = conf.instance["visualize"]["general"]["colormap"]
except Exception: # <-- swallows a typo'd key AND a real failure
name = "autoarray"
if name == "autoarray":
from autoarray.plot.segmentdata import register
register()
return name
Consumers, all of which default colormap=None and then call _default_colormap():
autoarray/plot/array.py:140-142 → imshow(cmap=colormap) (lines 180, 187)
autoarray/plot/grid.py:105-107 → scatter(cmap=colormap) (lines 118-124)
autoarray/plot/inversion.py:79-81 → _plot_rectangular (imshow/pcolormesh, lines 198/214) and _plot_delaunay (tripcolor, line 269)
Everything above those three modules (autoarray/dataset/plot/, autoarray/fit/plot/, autoarray/inversion/plot/, PyAutoGalaxy's _resolve_colormap("default") in autogalaxy/util/plot_utils.py:97-102, PyAutoLens's tracer_plots.py / sensitivity_plots.py / fit_imaging_plots.py) either passes colormap through or leaves it None, so the config value reaches the raster call either way.
Implementation Steps
- PyAutoArray —
autoarray/plot/utils.py::_default_colormap(). Split the two failure modes:
- config unavailable / key absent (
ImportError, KeyError, AttributeError, autoconf's missing-key exception) → quiet fallback to "autoarray" (unchanged behaviour, no warning: a fresh install has no config yet).
- key present but the value neither
"autoarray" nor resolvable via matplotlib.colormaps → raise ValueError naming the config file, the key path (visualize/general.yaml → colormap), the offending value, and a hint to use any matplotlib colormap name.
- Do not leave a bare
except Exception.
- Sibling readers.
_conf_imshow_origin and _conf_output_format have the same bare-except shape. Tighten only if trivially safe in the same pass; otherwise note them in the PR as follow-up (they are not part of the acceptance gate).
- Tests —
PyAutoArray/test_autoarray/plot/test_utils.py. Add unit tests for _default_colormap() using the same conf.instance[...] mutate/restore idiom the existing tests use (see test_arcsec_labels_default_suffix_format):
- key absent → returns
"autoarray" (and the custom colormap registers)
- valid matplotlib name (
"magma") → returned verbatim
- bogus name (
"nonexistent_cmap") → ValueError mentioning colormap and the bad value
No JAX in unit tests.
- Docs —
PyAutoArray/autoarray/config/visualize/README.md. Add a "Changing the colormap" section: the config key (global) and the colormap= argument on any plot_* function (per-figure), plus a note that array_overlay is deliberately fixed at Greys and that the weak-lensing / cluster plots use semantically-chosen fixed maps.
- Acceptance demo (not committed). A scratchpad script that sets
colormap: magma, renders one imaging Array2D figure and one rectangular-mapper inversion figure to PNG, proving one config edit moves both.
- Euclid workspace (after the library PR opens).
euclid_strong_lens_modeling_pipeline/config/visualize/general.yaml → colormap: magma; add the same "Changing the colormap" section to that repo's config/visualize/README.md.
Key Files
PyAutoArray/autoarray/plot/utils.py — _default_colormap() and its bare-except siblings
PyAutoArray/autoarray/plot/array.py, grid.py, inversion.py — the three consumers
PyAutoArray/autoarray/plot/segmentdata.py — the bundled autoarray colormap and its register()
PyAutoArray/autoarray/config/visualize/general.yaml — the colormap: key (stays autoarray)
PyAutoArray/test_autoarray/plot/test_utils.py — where the new tests go
PyAutoArray/autoarray/config/visualize/README.md — library-side docs
euclid_strong_lens_modeling_pipeline/config/visualize/general.yaml + README.md — the magma default
Documented deliberate exceptions (audited, not changed)
autoarray/plot/array.py:208 — cmap="Greys" for the array_overlay (a second array drawn over the main one; it must contrast with whatever the main colormap is).
autolens/weak/plot/weak_dataset_plots.py — viridis (ellipticities), twilight (cyclic position angles), magma (noise map).
autolens/weak/plot/fit_weak_plots.py:119 — RdBu_r (diverging, centred residuals).
autolens/weak/plot/convergence_plots.py:202 — magma.
autolens/cluster/plot/cluster_plots.py:49 — CLUSTER_CMAP = "gnuplot2".
autolens/potential_correction/* and autogalaxy/gui/clicker.py — jet in research/GUI-only code paths.
Original Prompt
Click to expand starting prompt
# Colormap control: audit the cmap lever end-to-end and default the Euclid configs to magma
Type: feature
Target: PyAutoLens
Repos:
- PyAutoArray
- PyAutoLens
- autolens_workspace
- euclid_strong_lens_modeling_pipeline
Themes:
- visualization
- euclid
Difficulty: small-medium
Autonomy: safe
Priority: high
Status: formalised
Epic: euclid-dr1-prep
Phase: 0
Parent: draft/feature/euclid/euclid_dr1_prep_epic.md
Filed: 2026-08-28
Phase 0 of 10 in the Euclid DR1 preparation epic. Independent of every other phase —
it can start immediately and does not gate anything.
User request (verbatim):
"""
0) change default cmap to magma: lots of people compain about the cmap so make sure there is functionality to adjust
cmap used throughout autolens and update euclid repo configs so that magma is used.
"""
## What already exists (surveyed 2026-08-28 — do not rebuild it)
The lever is already there. `PyAutoArray/autoarray/plot/utils.py::_default_colormap()`
reads `conf.instance["visualize"]["general"]["colormap"]` and falls back to the bundled
custom `"autoarray"` colormap (registered from
`PyAutoArray/autoarray/plot/segmentdata.py`, `COLORMAP_NAME = "autoarray"`). The key
`colormap: autoarray` is present in all three `config/visualize/general.yaml` files
(PyAutoArray, autolens_workspace, euclid_strong_lens_modeling_pipeline).
So the task is **audit + default change**, not lever construction.
## Deliverables
1. **Reach audit.** Confirm the config value actually reaches *every* 2D plotting
surface, not just `plot/array.py` (which is the only confirmed consumer —
`array.py:140-142` calls `_default_colormap()`). Check at minimum
`PyAutoArray/autoarray/plot/inversion.py` (`_plot_rectangular`, `_plot_delaunay` both
take a `colormap` argument — trace who supplies it), `plot/grid.py`, and any
hardcoded colormap literal. `array.py:208` hardcodes `cmap="Greys"` for the
`array_overlay`; decide whether that is deliberate (it probably is) and document it
rather than silently leaving it undocumented.
2. **Per-figure override.** Verify a user can override the colormap for a single figure
through the public plot API without editing config, and document how. If no such
route exists, add the minimal one — prefer the lean existing lever over a new class.
3. **The silent fallback.** `_default_colormap()` (and its siblings
`_conf_imshow_origin`, `_conf_output_format`) wrap the config read in a bare
`except Exception`. A typo'd or missing key therefore fails silently to `autoarray`
and the user never learns their setting was ignored. Tighten this so a genuinely
absent config falls back quietly but a *malformed* value is loud. (Workspace
convention: no silent guards.)
4. **Magma in the Euclid configs.** Set `colormap: magma` in
`euclid_strong_lens_modeling_pipeline/config/visualize/general.yaml`. Leave the
PyAutoArray/autolens_workspace defaults alone unless the user asks otherwise — the
request scopes the magma change to "euclid repo configs".
5. **Documentation.** One short, discoverable place telling users how to change the
colormap (config key + per-figure override). The `config/visualize/README.md` files
are the natural home.
## Acceptance / gate
- A single config edit changes the colormap on every 2D figure the pipeline produces
(imaging data, fits, residuals, inversion reconstructions), demonstrated on at least
one imaging figure and one inversion figure.
- A malformed `colormap` value produces a clear error or warning, not a silent revert.
- The Euclid pipeline repo renders in magma out of the box.
- Nothing else in the epic gates on this; it can ship on its own.
Overview
Users regularly complain about the default colormap. The lever to change it already exists —
PyAutoArray/autoarray/plot/utils.py::_default_colormap()readsvisualize/general.yaml → colormapand every 2D plot function takes acolormapargument — but it is undocumented, and the config read is wrapped in a bareexcept Exceptionso a typo'd key or an unknown colormap name silently reverts to the bundledautoarraymap with no warning. This task audits the lever end-to-end, makes malformed values loud, documents the two override routes, and defaults the Euclid pipeline repo tomagma.Phase 0 of 10 in the
euclid-dr1-prepepic. Independent of every other phase — it gates nothing and nothing gates it.Plan
colormapconfig key actually reaches every 2D plotting surface across PyAutoArray / PyAutoGalaxy / PyAutoLens, and document the deliberate exceptions (hardcoded, semantically-chosen colormaps) rather than leaving them silent._default_colormap()loud: an absent config still falls back quietly toautoarray, but a present but unresolvable colormap name raises a clearValueErrornaming the config key and the bad value. Replace the bareexcept Exceptionwith a narrow one.colormap=on everyplot_*entry point).config/visualize/README.mdfiles (PyAutoArray + the Euclid pipeline repo).colormap: magmaineuclid_strong_lens_modeling_pipeline/config/visualize/general.yaml. Leave PyAutoArray andautolens_workspaceonautoarray.Detailed implementation plan
Affected Repositories
PyAutoLens / PyAutoGalaxy are audited but not edited — their plot surfaces already thread
colormapdown toautoarray'splot_array/plot_grid/plot_mapper.Branch Survey
worktree_check_conflict cmap-magma-default PyAutoArray euclid_strong_lens_modeling_pipeline→ no conflict.Suggested branch:
feature/cmap-magma-defaultThe lever as it stands (surveyed 2026-08-28)
Consumers, all of which default
colormap=Noneand then call_default_colormap():autoarray/plot/array.py:140-142→imshow(cmap=colormap)(lines 180, 187)autoarray/plot/grid.py:105-107→scatter(cmap=colormap)(lines 118-124)autoarray/plot/inversion.py:79-81→_plot_rectangular(imshow/pcolormesh, lines 198/214) and_plot_delaunay(tripcolor, line 269)Everything above those three modules (
autoarray/dataset/plot/,autoarray/fit/plot/,autoarray/inversion/plot/, PyAutoGalaxy's_resolve_colormap("default")inautogalaxy/util/plot_utils.py:97-102, PyAutoLens'stracer_plots.py/sensitivity_plots.py/fit_imaging_plots.py) either passescolormapthrough or leaves itNone, so the config value reaches the raster call either way.Implementation Steps
autoarray/plot/utils.py::_default_colormap(). Split the two failure modes:ImportError,KeyError,AttributeError, autoconf's missing-key exception) → quiet fallback to"autoarray"(unchanged behaviour, no warning: a fresh install has no config yet)."autoarray"nor resolvable viamatplotlib.colormaps→ raiseValueErrornaming the config file, the key path (visualize/general.yaml → colormap), the offending value, and a hint to use any matplotlib colormap name.except Exception._conf_imshow_originand_conf_output_formathave the same bare-except shape. Tighten only if trivially safe in the same pass; otherwise note them in the PR as follow-up (they are not part of the acceptance gate).PyAutoArray/test_autoarray/plot/test_utils.py. Add unit tests for_default_colormap()using the sameconf.instance[...]mutate/restore idiom the existing tests use (seetest_arcsec_labels_default_suffix_format):"autoarray"(and the custom colormap registers)"magma") → returned verbatim"nonexistent_cmap") →ValueErrormentioningcolormapand the bad valueNo JAX in unit tests.
PyAutoArray/autoarray/config/visualize/README.md. Add a "Changing the colormap" section: the config key (global) and thecolormap=argument on anyplot_*function (per-figure), plus a note thatarray_overlayis deliberately fixed atGreysand that the weak-lensing / cluster plots use semantically-chosen fixed maps.colormap: magma, renders one imagingArray2Dfigure and one rectangular-mapper inversion figure to PNG, proving one config edit moves both.euclid_strong_lens_modeling_pipeline/config/visualize/general.yaml→colormap: magma; add the same "Changing the colormap" section to that repo'sconfig/visualize/README.md.Key Files
PyAutoArray/autoarray/plot/utils.py—_default_colormap()and its bare-except siblingsPyAutoArray/autoarray/plot/array.py,grid.py,inversion.py— the three consumersPyAutoArray/autoarray/plot/segmentdata.py— the bundledautoarraycolormap and itsregister()PyAutoArray/autoarray/config/visualize/general.yaml— thecolormap:key (staysautoarray)PyAutoArray/test_autoarray/plot/test_utils.py— where the new tests goPyAutoArray/autoarray/config/visualize/README.md— library-side docseuclid_strong_lens_modeling_pipeline/config/visualize/general.yaml+README.md— the magma defaultDocumented deliberate exceptions (audited, not changed)
autoarray/plot/array.py:208—cmap="Greys"for thearray_overlay(a second array drawn over the main one; it must contrast with whatever the main colormap is).autolens/weak/plot/weak_dataset_plots.py—viridis(ellipticities),twilight(cyclic position angles),magma(noise map).autolens/weak/plot/fit_weak_plots.py:119—RdBu_r(diverging, centred residuals).autolens/weak/plot/convergence_plots.py:202—magma.autolens/cluster/plot/cluster_plots.py:49—CLUSTER_CMAP = "gnuplot2".autolens/potential_correction/*andautogalaxy/gui/clicker.py—jetin research/GUI-only code paths.Original Prompt
Click to expand starting prompt