diff --git a/autogalaxy/analysis/model_util.py b/autogalaxy/analysis/model_util.py index 0e5ca526..25a65eb4 100644 --- a/autogalaxy/analysis/model_util.py +++ b/autogalaxy/analysis/model_util.py @@ -204,6 +204,39 @@ def mge_point_model_from( return af.Model(Basis, profile_list=gaussian_list) +def hilbert_pixels_from_pixel_scale(pixel_scale: float) -> int: + """ + Return the number of Hilbert-curve pixels appropriate for a given image pixel scale. + + The Hilbert pixel count controls the resolution of the Hilbert-curve ordering used + in adaptive source-plane pixelizations. Finer pixel scales resolve smaller angular + features and therefore benefit from a higher Hilbert resolution. + + Parameters + ---------- + pixel_scale + The pixel scale of the image in arcseconds per pixel. + + Returns + ------- + int + The recommended number of Hilbert pixels. + """ + if not np.isfinite(pixel_scale) or pixel_scale <= 0: + raise ValueError( + f"hilbert_pixels_from_pixel_scale requires pixel_scale to be finite and > 0, got {pixel_scale}." + ) + + if pixel_scale > 0.06: + return 1000 + elif pixel_scale > 0.04: + return 1250 + elif pixel_scale >= 0.03: + return 1500 + else: + return 1750 + + def simulator_start_here_model_from(): from autogalaxy.profiles.light.snr import Sersic diff --git a/test_autogalaxy/analysis/test_model_util.py b/test_autogalaxy/analysis/test_model_util.py index 7739ce67..c8f34825 100644 --- a/test_autogalaxy/analysis/test_model_util.py +++ b/test_autogalaxy/analysis/test_model_util.py @@ -58,6 +58,48 @@ def test__mge_point_model_from__shared_centre_and_ell_comps(): assert model.prior_count == 4 +def test__hilbert_pixels_from_pixel_scale__above_006(): + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.07) == 1000 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.1) == 1000 + + +def test__hilbert_pixels_from_pixel_scale__between_004_and_006(): + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.05) == 1250 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.061) == 1000 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.041) == 1250 + + +def test__hilbert_pixels_from_pixel_scale__between_003_and_004(): + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.03) == 1500 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.035) == 1500 + + +def test__hilbert_pixels_from_pixel_scale__below_003(): + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.02) == 1750 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.01) == 1750 + + +def test__hilbert_pixels_from_pixel_scale__raises_for_non_positive(): + with pytest.raises(ValueError): + ag.model_util.hilbert_pixels_from_pixel_scale(0.0) + with pytest.raises(ValueError): + ag.model_util.hilbert_pixels_from_pixel_scale(-0.05) + + +def test__hilbert_pixels_from_pixel_scale__raises_for_non_finite(): + with pytest.raises(ValueError): + ag.model_util.hilbert_pixels_from_pixel_scale(float("nan")) + with pytest.raises(ValueError): + ag.model_util.hilbert_pixels_from_pixel_scale(float("inf")) + + +def test__hilbert_pixels_from_pixel_scale__boundary_values(): + # Exactly 0.06 is NOT > 0.06, so falls to next branch (> 0.04 → 1250) + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.06) == 1250 + # Exactly 0.04 is NOT > 0.04, but IS >= 0.03 → 1500 + assert ag.model_util.hilbert_pixels_from_pixel_scale(0.04) == 1500 + + def test__mge_point_model_from__centre_prior_bounds(): """ When a custom centre is supplied the UniformPrior limits shift by ±0.1