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
37 changes: 29 additions & 8 deletions config/latent.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
# Workspace overrides for the library lensing latent toggles. The
# PyAutoLens library defaults every key to `false` so existing fits stay
# unchanged on upgrade and unaware of `magzero`. Enabling them here
# means a workspace fit produces real latent output as long as the user
# also passes `magzero` to `al.AnalysisImaging(...)` when one is needed.
# PyAutoLens library defaults the three raw-flux keys to `true` (they
# need no instrument inputs) and the µJy / dimensionless variants to
# `false`. Enabling the µJy ones here means a workspace fit produces
# real microjansky output as long as the user also passes `magzero` to
# `al.AnalysisImaging(...)` — without `magzero` they return NaN and emit
# 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_lens_flux_mujy — integrated lens-galaxy flux in microjanskies.
# Requires magzero. NaN when lens has no light profile.
# total_lens_flux — integrated lens-galaxy flux in the fit's raw image
# units. No instrument inputs required. NaN when lens has no light profile.
total_lens_flux: true

# total_lensed_source_flux — image-plane source flux after lensing, in
# raw image units. No instrument inputs required.
total_lensed_source_flux: true

# total_source_flux — source-plane intrinsic source flux in raw image
# units. Uses fit.tracer_linear_light_profiles_to_light_profiles so MGE /
# linear light profiles work correctly. No instrument inputs required.
total_source_flux: true

# total_lens_flux_mujy — same as total_lens_flux but converted to
# microjanskies. Requires magzero on AnalysisImaging; NaN + one warning
# per process if missing.
total_lens_flux_mujy: true

# total_lensed_source_flux_mujy — image-plane source flux after lensing,
Expand All @@ -29,3 +45,8 @@ magnification: true
# zero-contour of the tangential eigenvalue field.
# magzero is not required.
effective_einstein_radius: true

# autogalaxy library default (loaded by autoconf into the same `latent`
# conf node) — explicitly disabled here to silence the cross-library
# "unknown latent" warning that would otherwise fire on every fit.
total_galaxy_0_flux: false
66 changes: 43 additions & 23 deletions scripts/guides/results/latent_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

__Contents__

- Lensing Latents in PyAutoLens: The five library-shipped latents and what each one means physically.
- Lensing Latents in PyAutoLens: The eight library-shipped latents and what each one means physically.
- Toggling Latents: The workspace ``config/latent.yaml`` override.
- Model Fit: A quick fit that produces real latent output for the loading section.
- Loading Latent Results: Reading the latent samples via ``analysis.compute_latent_samples(result.samples)``.
Expand All @@ -36,20 +36,38 @@

The library ships a flat registry of named latent functions at ``autolens.analysis.latent.LATENT_FUNCTIONS``,
backed by the toggle file ``autolens/config/latent.yaml``. Each entry maps a snake-case latent name to a Python
function that takes a fit, magzero, and ``xp`` and returns a scalar value. The day-1 catalogue has five entries:
function that takes a fit, magzero, and ``xp`` and returns a scalar value. The catalogue splits into three
groups: raw-flux latents (no instrument inputs, default-on), microjansky variants (require ``magzero``,
default-off), and the dimensionless lensing latents (``magnification``, ``effective_einstein_radius``).

- ``total_lens_flux_mujy``total integrated flux of the lens galaxy in microjanskies. Sum of the lens's
image-plane contribution to ``fit.galaxy_image_dict[fit.tracer.galaxies[0]]``, converted via ``magzero``.
Useful for stellar-mass-light scaling and photometric inference.
Raw-flux latentssum the relevant model image in the fit's raw image units. Same units as
``dataset.data.array`` (typically e- s^-1 for HST, MJy/sr for JWST). See
``scripts/guides/units/flux.py`` for how to convert to microjanskies or AB magnitudes in post.

- ``total_lensed_source_flux_mujy`` — total integrated source-galaxy flux in the image plane after lensing
(i.e. with magnification baked in). Sum of ``fit.galaxy_image_dict[fit.tracer.galaxies[-1]]``, converted
via ``magzero``.
- ``total_lens_flux`` — total integrated flux of the lens galaxy. Sum of
``fit.galaxy_image_dict[fit.tracer.galaxies[0]].array``. Returns NaN when the lens has no light profile.

- ``total_source_flux_mujy`` — the source's intrinsic flux in the source plane (before lensing). Computed
from the source galaxy's light profile evaluated on the workspace's light-profile grid. Critically uses
``fit.tracer_linear_light_profiles_to_light_profiles`` rather than ``fit.tracer`` so that MGE / linear
light profiles report the inversion-solved intensities rather than zero.
- ``total_lensed_source_flux`` — image-plane integrated flux of the source galaxy after lensing (with
magnification baked in). Sum of ``fit.galaxy_image_dict[fit.tracer.galaxies[-1]].array``.

- ``total_source_flux`` — the source's intrinsic flux in the source plane (before lensing). Computed from
the source's light profile evaluated on the workspace's light-profile grid. Critically uses
``fit.tracer_linear_light_profiles_to_light_profiles`` rather than ``fit.tracer`` so MGE / linear light
profiles report the inversion-solved intensities rather than zero.

Microjansky variants — same image sources as the raw-flux trio, but with the AB-mag → µJy conversion baked
in. Each one requires ``magzero`` on the analysis; if it's missing, the latent returns NaN and the library
emits a single warning per process per latent name (your search still completes — the cost is just an empty
column).

- ``total_lens_flux_mujy`` — ``total_lens_flux`` in microjanskies. Useful for stellar-mass-light scaling and
photometric inference.

- ``total_lensed_source_flux_mujy`` — ``total_lensed_source_flux`` in microjanskies.

- ``total_source_flux_mujy`` — ``total_source_flux`` in microjanskies.

Dimensionless lensing latents — no instrument inputs, no µJy variant.

- ``magnification`` — dimensionless ratio of ``total_lensed_source_flux_mujy / total_source_flux_mujy``.
This is the empirical flux-amplification factor implied by the lens model and source light profile. Source-
Expand All @@ -64,18 +82,19 @@
tangential critical curve — the critical curve isn't circular for non-spherical mass models, but its
enclosed area is the right physical quantity for mass-within-Einstein-radius estimates.

All five default to ``false`` in the library yaml (so existing fits stay unchanged on upgrade), and the four
flux-derived latents require ``magzero`` to be passed to ``al.AnalysisImaging(...)`` — if it's missing the
latent computation raises ``ValueError``. ``magnification`` and ``effective_einstein_radius`` don't need
``magzero``.
The raw-flux latents default to ``true`` in the library yaml — they cost essentially nothing and produce a
universally useful column. The µJy variants and the two dimensionless latents default to ``false`` so existing
fits and instrument-naive workflows stay unchanged on upgrade.
"""

"""
__Toggling Latents__

The library defaults every latent to ``false`` for the regression-safety reasons described above. To opt in,
edit your workspace's ``config/latent.yaml`` and set the keys you want to ``true``. This workspace ships such
a file at ``autolens_workspace/config/latent.yaml`` with all five lensing latents enabled.
The library defaults the three raw-flux latents to ``true`` and everything else to ``false`` for the
regression-safety reasons described above. To opt in to the µJy variants, dimensionless lensing latents, or to
disable a default-on raw-flux latent, edit your workspace's ``config/latent.yaml`` and set the keys you want.
This workspace ships such a file at ``autolens_workspace/config/latent.yaml`` with all eight lensing latents
enabled.

Workspace ``config/`` values shadow the library defaults — PyAutoFit's ``conf.instance`` searches the workspace
``config/`` directory first, so toggling a latent in your workspace yaml is enough to enable it without modifying
Expand All @@ -91,8 +110,9 @@
``simple__no_lens_light`` dataset. We use an Isothermal lens mass and an MGE source — fast enough to run in
test mode while still producing a real posterior over the magnification and Einstein-radius latents.

We pass ``magzero=25.0`` to ``al.AnalysisImaging`` for the flux-derived latents. The Einstein-radius and
magnification latents don't need it, but the others would raise without it.
We pass ``magzero=25.0`` to ``al.AnalysisImaging`` so the three µJy latents populate with real values
(without it they'd be NaN and the library would log a single warning per latent name per process). The raw-flux
trio, Einstein-radius and magnification latents don't need ``magzero``.
"""
dataset_name = "simple__no_lens_light"
dataset_path = Path("dataset") / "imaging" / dataset_name
Expand Down Expand Up @@ -226,8 +246,8 @@ def compute_latent_variables(self, parameters, model):

"""
A fit that uses ``AnalysisImagingWithMassAxisRatio`` produces a ``latent.csv`` with one extra column
(``mass_axis_ratio``) on top of the five library defaults. We don't run a second fit here — the pattern above
is the full recipe.
(``mass_axis_ratio``) on top of the eight library defaults (raw-flux + µJy + dimensionless lensing). We don't
run a second fit here — the pattern above is the full recipe.
"""

"""
Expand Down
54 changes: 54 additions & 0 deletions scripts/guides/units/flux.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

- **Zero Point:** In astronomy, a zero point refers to a reference value used in photometry and spectroscopy to.
- **Total Flux:** A key quantity for computing the magnitudes of galaxies is the total flux of a light profile.
- **Latent Variables:** Reading the same total flux directly from the `latent.csv` of a completed fit.

__Zero Point__

Expand Down Expand Up @@ -239,7 +240,60 @@
- The HST PHOTNU value, in units of Jy (e s^-1), which converts to Janskys, which is often used by SED fitting
software.

__Latent Variables: Total Flux Directly from the Fit__

The examples above all computed total flux by hand: build a light profile, sample it on a grid, sum the image, then
apply the zero point. PyAutoLens 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.

Three lensing flux latents ship default-on (they need no instrument inputs and run on every fit unless disabled in
`config/latent.yaml`):

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

- `total_lensed_source_flux` — image-plane integrated flux of the source galaxy after lensing. This is the source
flux as observed: stretched, multiplied, and distorted by the lens. Same raw units.

- `total_source_flux` — source-plane intrinsic flux of the source galaxy: the flux the source would have if the
lens weren't there. Computed via `fit.tracer_linear_light_profiles_to_light_profiles` so that linear light
profiles (MGEs, pixelizations) work correctly. The ratio
`total_lensed_source_flux / total_source_flux` is the integrated magnification (also recorded directly as the
`magnification` latent).

To convert any of these to AB magnitudes or microjanskies, apply the same zero-point recipe used above. Suppose
you have an HST F814W fit with the F814W zero point of 25.943; reading the lens galaxy flux 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_lens_flux = pd.read_csv(search.paths.output_path / "latent" / "samples.csv")["total_lens_flux"].iloc[-1]
total_lens_flux = 1234.5 # e- s^-1

zero_point_f814w = 25.943
ab_mag_lens = ab_mag_via_flux_from(flux=total_lens_flux, magzero=zero_point_f814w)
flux_mujy_lens = flux_mujy_via_ab_mag_from(ab_mag=ab_mag_lens)

"""
The two helpers used above are the same ones the library uses internally to populate the `_mujy` variants of the
latents (`total_lens_flux_mujy`, `total_lensed_source_flux_mujy`, `total_source_flux_mujy`). Those variants are
default-off because they need a `magzero` you supply per-instrument. If you have a single fixed zero-point you can
flip them on by:

1. Setting `total_lens_flux_mujy: true` (and friends) in your project's `config/latent.yaml`.
2. Passing `magzero=<value>` when constructing the analysis:
`analysis = al.AnalysisImaging(dataset=dataset, magzero=25.943)`.

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

Finish.
"""
Loading