From b88fc6b8aba1a65af58ed61b66398afa5554aa0f Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Sun, 27 Sep 2026 12:25:59 +0100 Subject: [PATCH] fix(config): configure Delaunay.areas_factor and dPIE ra/rs notation priors/mesh/delaunay.yaml was a bare `Delaunay:`, so af.Model(ag.mesh.Delaunay) (and al.mesh.Delaunay) reported "areas_factor Prior Missing". Configure it as a Constant at the class default (0.5), the value autolens_workspace already sets. notation.yaml had no label/label_format for the dPIE `ra` and `rs` parameters, so both fell back to the first-letter label "r". Add r_{\rm a} / r_{\rm s} and '{:.4f}', matching autolens_workspace. Tests: Delaunay model has no missing prior; dPIE ra/rs labels are not the fallback (both red before the config change). The model-figure semantics test used Delaunay.areas_factor as its real-class witness of the `missing` state; it now uses CurvatureMask.coefficient (still unconfigured), and the Delaunay test pins areas_factor as a fixed Constant. Refs PyAutoLabs/PyAutoMind#441 Co-Authored-By: Claude Opus 5.5 --- autogalaxy/config/notation.yaml | 4 +++ autogalaxy/config/priors/mesh/delaunay.yaml | 3 ++ .../total/test_dual_pseudo_isothermal_mass.py | 16 ++++++++++ .../profiles/test_model_figure_semantics.py | 31 ++++++++++++------- test_autogalaxy/test_priors_config.py | 15 +++++++++ 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/autogalaxy/config/notation.yaml b/autogalaxy/config/notation.yaml index 50d6bdded..f37e7c839 100644 --- a/autogalaxy/config/notation.yaml +++ b/autogalaxy/config/notation.yaml @@ -47,10 +47,12 @@ label: outer_slope: t_{\rm 2} overdens: \Delta_{\rm vir} pixels: N_{\rm pix} + ra: r_{\rm a} radius_break: R_{\rm b} redshift: z redshift_object: z_{\rm obj} redshift_source: z_{\rm src} + rs: r_{\rm s} scale_radius: R_{\rm s} scatter: \sigma separation: s @@ -128,12 +130,14 @@ label_format: outer_slope: '{:.4f}' overdens: '{:.4f}' pixels: '{:.4f}' + ra: '{:.4f}' radius: '{:.4f}' radius_break: '{:.4f}' redshift: '{:.4f}' redshift_object: '{:.4f}' redshift_source: '{:.4f}' rho: '{:.4f}' + rs: '{:.4f}' scale_radius: '{:.4f}' separation: '{:.4f}' sersic_index: '{:.4f}' diff --git a/autogalaxy/config/priors/mesh/delaunay.yaml b/autogalaxy/config/priors/mesh/delaunay.yaml index 604de83de..4d6167f07 100644 --- a/autogalaxy/config/priors/mesh/delaunay.yaml +++ b/autogalaxy/config/priors/mesh/delaunay.yaml @@ -1 +1,4 @@ Delaunay: + areas_factor: + type: Constant + value: 0.5 diff --git a/test_autogalaxy/profiles/mass/total/test_dual_pseudo_isothermal_mass.py b/test_autogalaxy/profiles/mass/total/test_dual_pseudo_isothermal_mass.py index 7ac95fb5a..1a7aa4a4b 100644 --- a/test_autogalaxy/profiles/mass/total/test_dual_pseudo_isothermal_mass.py +++ b/test_autogalaxy/profiles/mass/total/test_dual_pseudo_isothermal_mass.py @@ -317,6 +317,22 @@ def test__default_class__supports_model_composition(): assert model_sph.prior_count == 9 +def test__ra_rs_have_notation_labels_not_the_first_letter_fallback(): + # With no notation entry autofit labels a parameter by its first letter, + # which renders both `ra` and `rs` as "r" in corner plots and tables. + import autofit as af + + labels = dict( + zip( + af.Model(ag.mp.dPIEPotential).parameter_names, + af.Model(ag.mp.dPIEPotential).parameter_labels, + ) + ) + + assert labels["ra"] == r"r_{\rm a}" + assert labels["rs"] == r"r_{\rm s}" + + def test__from_b0__returns_internal_parameterization(): # The non-standard construction path: dPIEMass.from_b0 / dPIEMassSph.from_b0 # return the internal (ra, rs, b0) classes with the inputs passed through. diff --git a/test_autogalaxy/profiles/test_model_figure_semantics.py b/test_autogalaxy/profiles/test_model_figure_semantics.py index 895f60384..ebefb303e 100644 --- a/test_autogalaxy/profiles/test_model_figure_semantics.py +++ b/test_autogalaxy/profiles/test_model_figure_semantics.py @@ -180,25 +180,28 @@ def test__point_centre_is_a_free_tuple(): # ---------------------------------------------------------------------------- -# the `missing` state -- unset configuration on a `Delaunay` mesh +# the `missing` state -- unset configuration on a real class # ---------------------------------------------------------------------------- -def test__delaunay_areas_factor_has_no_prior_configured_and_is_missing(): - spec = af.GraphSpec.from_model(af.Model(ag.mesh.Delaunay)) +def test__curvature_mask_coefficient_has_no_prior_configured_and_is_missing(): + # `CurvatureMask` ships no prior for `coefficient`, so it is the real-class + # witness of the `missing` state (it was `Delaunay.areas_factor` until that + # was configured as a Constant). + spec = af.GraphSpec.from_model(af.Model(ag.reg.CurvatureMask)) - row = rows_of(spec)["areas_factor"] + row = rows_of(spec)["coefficient"] assert row.sampling == "missing" assert row.prior_cls_name == "ConfigException" assert spec.counts["missing"] == 1 - presentation = af.ModelPlotter(af.Model(ag.mesh.Delaunay)).presentation() + presentation = af.ModelPlotter(af.Model(ag.reg.CurvatureMask)).presentation() - assert "areas_factor · missing" in pill_texts(presentation) + assert "coefficient · missing" in pill_texts(presentation) -def test__delaunay_pixels_and_zeroed_pixels_are_fixed_not_missing(): +def test__delaunay_pixels_zeroed_pixels_and_areas_factor_are_fixed_not_missing(): """ Measured, not assumed. @@ -206,16 +209,20 @@ def test__delaunay_pixels_and_zeroed_pixels_are_fixed_not_missing(): to be three ``missing`` rows. They are not: ``pixels: int`` has no default, so ``af.Model`` fills the slot with ``af.Model(int)`` -- a *fixed* row by rule R7, never a ``ConfigException`` -- and ``zeroed_pixels: Optional[int] = - 0`` simply takes its default. Only ``areas_factor`` is genuinely unset - configuration. This test pins that distinction so the figure cannot start - calling an unset int "missing" without someone noticing. + 0`` simply takes its default. ``areas_factor`` is configured as a + ``Constant`` (``priors/mesh/delaunay.yaml``), so it is fixed too. This test + pins that distinction so the figure cannot start calling an unset int + "missing" without someone noticing. """ spec = af.GraphSpec.from_model(af.Model(ag.mesh.Delaunay)) rows = rows_of(spec) assert rows["pixels"].sampling == "fixed" + assert rows["areas_factor"].sampling == "fixed" + assert rows["areas_factor"].prior_cls_name == "Constant" assert [row.name for row in spec.root.rows] == ["pixels", "areas_factor"] + assert spec.counts["missing"] == 0 set_spec = af.GraphSpec.from_model( af.Model(ag.mesh.Delaunay, pixels=500, zeroed_pixels=0) @@ -223,8 +230,8 @@ def test__delaunay_pixels_and_zeroed_pixels_are_fixed_not_missing(): set_rows = set_spec.root.rows assert [row.name for row in set_rows] == ["pixels", "zeroed_pixels", "areas_factor"] - assert [row.sampling for row in set_rows] == ["fixed", "fixed", "missing"] - assert set_spec.counts["missing"] == 1 + assert [row.sampling for row in set_rows] == ["fixed", "fixed", "fixed"] + assert set_spec.counts["missing"] == 0 # ---------------------------------------------------------------------------- diff --git a/test_autogalaxy/test_priors_config.py b/test_autogalaxy/test_priors_config.py index b1e25791f..b523840e3 100644 --- a/test_autogalaxy/test_priors_config.py +++ b/test_autogalaxy/test_priors_config.py @@ -236,3 +236,18 @@ def test__ellipse_multipole_scaled_model_resolves(): assert model.prior_count == 2 model.instance_from_prior_medians() + + +def test__delaunay_mesh_model_has_no_missing_prior(): + # `areas_factor` is a float `__init__` argument, so without a configured + # prior `af.Model` reports it as "Prior Missing" (the packaged file was a + # bare `Delaunay:`); it is a fixed Constant at the class default. + model = af.Model(ag.mesh.Delaunay, pixels=100) + + assert "Prior Missing" not in model.info + assert model.prior_count == 0 + assert model.areas_factor == 0.5 + + instance = model.instance_from_prior_medians() + + assert instance.areas_factor == 0.5