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
23 changes: 14 additions & 9 deletions config/latent.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# Workspace overrides for the library latent toggles. The PyAutoGalaxy
# library defaults every key to `false` (so existing fits stay unchanged
# on upgrade and unawares of `magzero`). Enabling them here means a
# workspace fit produces real latent output as long as the user also
# passes `magzero` to `ag.AnalysisImaging(...)`.
# library defaults `total_galaxy_0_flux` to `true` (no instrument inputs
# needed) and `total_galaxy_0_flux_mujy` to `false`. Enabling the µJy
# variant here means a workspace fit produces microjansky output as long
# as the user also passes `magzero` to `ag.AnalysisImaging(...)` — without
# `magzero` it returns NaN + one warning per process.
#
# Run `scripts/guides/results/latent_variables.py` for a tutorial on
# what each key means and how to extend the catalogue with custom
# latents in your own scripts.
# what each key means and `scripts/guides/units/flux.py` for how to
# convert a raw-flux latent to microjanskies in post.

# `total_galaxy_0_flux_mujy` — total integrated flux of `fit.galaxies[0]`
# in microjanskies (magzero-converted). Requires `magzero` via Analysis
# kwargs; raises loudly if missing.
# `total_galaxy_0_flux` — total integrated flux of `fit.galaxies[0]` in
# the fit's raw image units. No instrument inputs required.
total_galaxy_0_flux: true

# `total_galaxy_0_flux_mujy` — same flux converted to microjanskies via
# magzero. Requires `magzero` via Analysis kwargs; returns NaN + one
# warning per process if missing.
total_galaxy_0_flux_mujy: true
45 changes: 27 additions & 18 deletions scripts/guides/results/latent_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,36 @@
backed by the toggle file ``autogalaxy/config/latent.yaml``. Each entry maps a snake-case latent name to a Python
function that takes a fit, magzero, and ``xp`` (numpy / jax.numpy) and returns a scalar value.

The day-1 catalogue contains a single concrete latent:
The catalogue contains two related latents that pair as a raw-flux / unit-converted couplet:

- ``total_galaxy_0_flux_mujy`` — total integrated flux of the first galaxy in the fit (``fit.galaxies[0]``),
converted from the fit's linear flux units to microjanskies via the ``magzero`` keyword argument passed
to ``ag.AnalysisImaging``. Returns NaN when galaxy 0 has no light profile.
- ``total_galaxy_0_flux`` — total integrated flux of the first galaxy in the fit (``fit.galaxies[0]``) in the
fit's raw image units (typically e- s^-1 for HST, MJy/sr for JWST). Requires no instrument inputs and
ships default-on in the library yaml. Returns NaN when galaxy 0 has no light profile. See
``scripts/guides/units/flux.py`` for how to convert this raw flux to microjanskies or AB magnitudes in post.

- ``total_galaxy_0_flux_mujy`` — the same total flux converted to microjanskies via the ``magzero`` keyword
argument passed to ``ag.AnalysisImaging``. Default-off in the library yaml — opt in only when you have a
stable per-instrument zero-point. If you enable it without supplying ``magzero`` the column populates with
NaN and the library emits a single warning per process (your fit completes uninterrupted).

The catalogue is intentionally narrow at launch — the long-tail of useful galaxy latents will accrue over
time as users contribute the ones their science needs. See the "Contributing Upstream" section at the end of
this tutorial for how to add new ones.

Future library releases may extend the registry. The toggle layer below means new entries default to ``false``
in the library yaml, so adding a latent never changes the behaviour of an existing fit — users opt in by
enabling the key in their workspace ``config/latent.yaml``.
Future library releases may extend the registry. The toggle layer below means new entries can default either
way safely: a new raw-flux latent that requires no inputs can default-on, while anything needing instrument
metadata defaults-off so existing instrument-naive fits stay unchanged on upgrade.
"""

"""
__Toggling Latents__

The library defaults every latent to ``false`` in ``autogalaxy/config/latent.yaml``. This is deliberate: the
flux-derived latents require a ``magzero`` value via ``AnalysisImaging(..., magzero=...)`` kwargs, and enabling
them by default would crash any existing fit that doesn't pass ``magzero``. To opt in, you create or edit your
workspace's ``config/latent.yaml`` and set the keys you want to ``true``. This workspace ships such a file at
``autogalaxy_workspace/config/latent.yaml`` with ``total_galaxy_0_flux_mujy: true``.
The library defaults ``total_galaxy_0_flux: true`` (no instrument inputs needed) and
``total_galaxy_0_flux_mujy: false`` (you need to supply ``magzero``) in ``autogalaxy/config/latent.yaml``. The
default-off µJy variant is deliberate: it requires a ``magzero`` value via ``AnalysisImaging(..., magzero=...)``,
and the workspace fit you're running may not have one to hand. To opt in to the µJy column, edit your
workspace's ``config/latent.yaml`` and set ``total_galaxy_0_flux_mujy: true``. This workspace ships such a file
at ``autogalaxy_workspace/config/latent.yaml`` with both keys ``true``.

Workspace ``config/`` values shadow the library defaults — PyAutoFit's ``conf.instance`` searches the workspace
``config/`` directory first, then falls back to the library's bundled defaults. So toggling a latent in your
Expand All @@ -81,9 +88,10 @@
imaging dataset that ships with the workspace. The model is a single galaxy with a Sersic bulge — keeping it
small so the example runs in a reasonable time.

We pass ``magzero=25.0`` to ``ag.AnalysisImaging``. This is required by ``total_galaxy_0_flux_mujy`` (the flux
needs a photometric zero-point to convert into microjanskies). If you forget it, the latent computation will
raise ``ValueError`` with a message pointing here.
We pass ``magzero=25.0`` to ``ag.AnalysisImaging`` so ``total_galaxy_0_flux_mujy`` populates with a real value
rather than NaN. If you forget it, ``total_galaxy_0_flux_mujy`` will be NaN and the library will log a single
warning per process noting the conversion was skipped — the fit itself is unaffected, and the raw
``total_galaxy_0_flux`` column populates normally.
"""
dataset_name = "simple"
dataset_path = Path("dataset") / "imaging" / dataset_name
Expand Down Expand Up @@ -132,13 +140,14 @@
The returned object exposes the same API as the parameter ``Samples`` — ``median_pdf``, ``max_log_likelihood``,
``values_at_sigma_1``, and so on — but reports on the induced latent posterior rather than the parameter posterior.

Because ``total_galaxy_0_flux_mujy`` is the only enabled latent in this workspace, the returned instance only
exposes that single attribute. If you enable additional latents in the workspace yaml, they all appear as
attributes on the same instance.
Because both ``total_galaxy_0_flux`` and ``total_galaxy_0_flux_mujy`` are enabled in this workspace, the
returned instance exposes both attributes. If you enable additional latents in the workspace yaml, they all
appear as attributes on the same instance.
"""
latent_samples = analysis.compute_latent_samples(result.samples)

median_instance = latent_samples.median_pdf()
print(f"Median PDF total_galaxy_0_flux: {median_instance.total_galaxy_0_flux}")
print(
f"Median PDF total_galaxy_0_flux_mujy: {median_instance.total_galaxy_0_flux_mujy}"
)
Expand Down
48 changes: 47 additions & 1 deletion scripts/guides/units/flux.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

- **Zero Point:** Explanation of photometric zero points and their role in flux calibration.
- **Mega Janskys / steradian (MJy/sr): James Webb Space Telescope:** Convert JWST NIRCam light profile intensities to AB magnitudes.
- **Latent Variables:** Reading the same total flux directly from the `latent.csv` of a completed fit.

__Zero Point__

Expand All @@ -40,7 +41,7 @@
instrument that was used to observe the data.
"""

# from autoconf import setup_notebook; setup_notebook()
# from autoconf import setup_notebook; setup_notebook()

import numpy as np
import autogalaxy as ag
Expand Down Expand Up @@ -115,5 +116,50 @@
magnitude_ab = zero_point - 2.5 * np.log10(total_flux)

"""
__Latent Variables: Total Flux Directly from the Fit__

The example above computed the total flux by hand: build a light profile, sample it on a grid, sum the image, then
apply the zero point. PyAutoGalaxy does exactly this automatically as part of every fit and records the result as
a latent variable in the `latent/samples.csv` file beside the search output. You can skip the manual recipe
entirely and just read the column.

The raw-flux latent ships default-on (it needs no instrument inputs and runs on every fit unless disabled in
`config/latent.yaml`):

- `total_galaxy_0_flux` — total integrated flux of the first galaxy (`fit.galaxies[0]`), in the *raw* image
units the fit was performed in. For JWST data in MJy/sr, this is MJy/sr; for HST data in e- s^-1, this is
e- s^-1.

To convert this to AB magnitudes or microjanskies, apply the same zero-point recipe used above. Suppose you
have a JWST F444W fit and want the AB magnitude of the galaxy; reading the column from your result and
converting goes:
"""
from autogalaxy.imaging.model.latent import (
ab_mag_via_flux_from,
flux_mujy_via_ab_mag_from,
)

# Stand-in for what you'd read from `latent.csv` — in a real script this is one column of one row, e.g.
# total_galaxy_0_flux = pd.read_csv(search.paths.output_path / "latent" / "samples.csv")["total_galaxy_0_flux"].iloc[-1]
total_galaxy_0_flux = 1234.5 # MJy/sr

# JWST F444W zero-point computed exactly as in the MJy/sr section above.
ab_mag_galaxy = ab_mag_via_flux_from(flux=total_galaxy_0_flux, magzero=zero_point)
flux_mujy_galaxy = flux_mujy_via_ab_mag_from(ab_mag=ab_mag_galaxy)

"""
The two helpers used above are the same ones the library uses internally to populate the `_mujy` variant of the
latent (`total_galaxy_0_flux_mujy`). That variant is default-off because it needs a `magzero` you supply per
instrument. If you have a single fixed zero-point you can flip it on by:

1. Setting `total_galaxy_0_flux_mujy: true` in your project's `config/latent.yaml`.
2. Passing `magzero=<value>` when constructing the analysis:
`analysis = ag.AnalysisImaging(dataset=dataset, magzero=zero_point)`.

The latent dispatcher then writes the converted µJy column into `latent/samples.csv` directly, so you don't
have to run the conversion in post. If you enable the `_mujy` latent but forget the `magzero` keyword, the
column is populated with NaN and a single warning per process notes that the conversion was skipped — the fit
itself is unaffected.

Finish.
"""
Loading