diff --git a/notebooks/chapter_1_introduction/tutorial_0_visualization.ipynb b/notebooks/chapter_1_introduction/tutorial_0_visualization.ipynb index e14d694..1b15aa0 100644 --- a/notebooks/chapter_1_introduction/tutorial_0_visualization.ipynb +++ b/notebooks/chapter_1_introduction/tutorial_0_visualization.ipynb @@ -273,13 +273,8 @@ "`subplot_shape_to_figsize_factor` controls subplot sizes. The per-call options above are enough for this lesson.\n", "\n", "**\ud83e\udd16 Ask AI:** Why can logarithmic colour scaling make faint structure easier to see without increasing its\n", - "signal-to-noise ratio?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "signal-to-noise ratio?\n", + "\n", "__Visuals__\n", "\n", "A mask selects which pixels to use. Here an annular mask keeps a ring between 0.3 and 3.0 arcseconds from\n", @@ -312,13 +307,8 @@ "metadata": {}, "source": [ "Compare the masked plot with the original image: the central light is excluded from this view, not removed\n", - "from the original dataset. We keep the masked version in `masked_dataset` so `dataset` remains available." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "from the original dataset. We keep the masked version in `masked_dataset` so `dataset` remains available.\n", + "\n", "__Wrap Up__\n", "\n", "You have plotted an image, compared dataset panels and changed the display without changing the pixel values.\n", diff --git a/notebooks/chapter_3_pixelizations/tutorial_3_fit_problems.ipynb b/notebooks/chapter_3_pixelizations/tutorial_3_fit_problems.ipynb index 3f7e4f5..0984f7f 100644 --- a/notebooks/chapter_3_pixelizations/tutorial_3_fit_problems.ipynb +++ b/notebooks/chapter_3_pixelizations/tutorial_3_fit_problems.ipynb @@ -22,51 +22,8 @@ "- Why the mesh becomes a limitation\n", "- Why one regularization coefficient becomes a compromise\n", "- Why maximizing the evidence does not remove the compromise\n", - "- Wrap Up" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__Google Colab Setup__\n", - "\n", - "Set up Google Colab as in [the introductory notebook](https://github.com/PyAutoLabs/HowToGalaxy/blob/main/notebooks/chapter_1_introduction/tutorial_1_grids_and_galaxies.ipynb).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "cellView": "form", - "jupyter": { - "source_hidden": true - } - }, - "outputs": [], - "source": [ - "# @title Set up Google Colab { display-mode: \"form\" }\n", - "try:\n", - " import google.colab\n", - "except ImportError:\n", - " from autogalaxy import setup_colab as _setup_colab\n", - "else:\n", - " import importlib\n", - " import subprocess\n", - " import sys\n", - "\n", - " subprocess.check_call(\n", - " [sys.executable, \"-m\", \"pip\", \"install\", \"autonerves\", \"--no-deps\"]\n", - " )\n", - " _setup_colab = importlib.import_module(\"autonerves.setup_colab\")\n", + "- Wrap Up\n", "\n", - "_setup_colab.setup(\"howtogalaxy\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ "__When the best coefficient is not enough__\n", "\n", "We have learned how to reconstruct a galaxy and choose its regularization coefficient using Bayesian evidence.\n", @@ -98,18 +55,51 @@ "- Separating the limitations of mesh resolution and constant regularization.\n", "- Motivating adaptation to the galaxy\u2019s brightness distribution.\n", "\n", - "---" + "---\n", + "\n", + "__Three progressively compact galaxies__\n", + "\n", + "We use three S\u00e9rsic profiles with the same centre and elliptical shape.\n", + "\n", + "For the first, we choose a relatively large effective radius and a S\u00e9rsic index of `1.0`. For the next two, we decrease the effective radius and increase the S\u00e9rsic index. Their light becomes more concentrated, with a steeper brightness gradient near the centre." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "__Three progressively compact galaxies__\n", + "__Google Colab Setup__\n", "\n", - "We use three S\u00e9rsic profiles with the same centre and elliptical shape.\n", + "Set up Google Colab as in [the introductory notebook](https://github.com/PyAutoLabs/HowToGalaxy/blob/main/notebooks/chapter_1_introduction/tutorial_1_grids_and_galaxies.ipynb).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "jupyter": { + "source_hidden": true + } + }, + "outputs": [], + "source": [ + "# @title Set up Google Colab { display-mode: \"form\" }\n", + "try:\n", + " import google.colab\n", + "except ImportError:\n", + " from autogalaxy import setup_colab as _setup_colab\n", + "else:\n", + " import importlib\n", + " import subprocess\n", + " import sys\n", "\n", - "For the first, we choose a relatively large effective radius and a S\u00e9rsic index of `1.0`. For the next two, we decrease the effective radius and increase the S\u00e9rsic index. Their light becomes more concentrated, with a steeper brightness gradient near the centre." + " subprocess.check_call(\n", + " [sys.executable, \"-m\", \"pip\", \"install\", \"autonerves\", \"--no-deps\"]\n", + " )\n", + " _setup_colab = importlib.import_module(\"autonerves.setup_colab\")\n", + "\n", + "_setup_colab.setup(\"howtogalaxy\")" ] }, { @@ -175,13 +165,8 @@ "source": [ "There is no lensing transformation. All three images use the same sky coordinates, while the spatial resolution needed to describe their light changes.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Simulating the images__\n", "\n", "We now simulate the three galaxy images using the same image grid and telescope blurring.\n", @@ -299,13 +284,8 @@ "\n", "Next, we will reconstruct them using the same rectangular mesh and constant regularization scheme. For each dataset, we will scan the coefficient and inspect its evidence-preferred reconstruction.\n", "\n", - "We will compare alternative reconstructions **within each dataset**. We will not rank the three different simulated galaxies against one another using their absolute evidence values." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "We will compare alternative reconstructions **within each dataset**. We will not rank the three different simulated galaxies against one another using their absolute evidence values.\n", + "\n", "__Reconstructing the galaxies__\n", "\n", "We will reconstruct all three galaxies using a `25 \u00d7 25` rectangular mesh and `Constant` regularization.\n", @@ -354,13 +334,8 @@ "\n", "For now, the only reconstruction setting we vary is the regularization coefficient.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Finding the preferred regularization__\n", "\n", "As in tutorial 2, we evaluate a range of coefficients and compare their log evidences. We do this separately for each dataset: a coefficient suitable for the extended galaxy need not be suitable for either compact galaxy.\n", @@ -454,13 +429,8 @@ "\n", "We can now inspect the reconstructions knowing that we have selected their smoothing strengths systematically.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Starting with the extended galaxy__\n", "\n", "Let\u2019s begin with the extended galaxy.\n", @@ -531,13 +501,8 @@ "source": [ "A value around one is a useful reference for noise-level residuals, but it does not tell us whether those residuals form a spatial pattern. Keep the residual map alongside this number.\n", "\n", - "This extended-galaxy fit provides our baseline. Next, we will make the galaxy more compact without giving the mesh any additional resolution, and examine where the reconstruction begins to struggle." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "This extended-galaxy fit provides our baseline. Next, we will make the galaxy more compact without giving the mesh any additional resolution, and examine where the reconstruction begins to struggle.\n", + "\n", "__Making the galaxy more compact__\n", "\n", "Now inspect the compact galaxy.\n", @@ -606,13 +571,8 @@ "\n", "The question is therefore no longer simply \u201cHave we chosen the wrong coefficient?\u201d We need to ask whether our mesh and regularization scheme can represent this galaxy adequately.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__A very compact galaxy__\n", "\n", "Our final galaxy has an effective radius of just `0.1` arcsec and a S\u00e9rsic index of `4.0`. Its light rises steeply towards the centre, placing a greater demand on the reconstruction.\n", @@ -689,13 +649,8 @@ "\n", "These galaxies also have different brightness distributions and signal-to-noise ratios. We should not interpret the comparison as a measurement of galaxy-size effects alone. Its purpose is to expose the practical difficulty of reconstructing increasingly concentrated light with an unchanged mesh and one smoothing coefficient.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Why the mesh becomes a limitation__\n", "\n", "Let\u2019s examine the first problem: where our galaxy pixels are placed.\n", @@ -748,13 +703,8 @@ "\n", "This motivates adapting the mesh to the **galaxy\u2019s brightness distribution**, which we will explore in the next tutorial.\n", "\n", - "First, there is a second limitation to understand. Even with enough mesh points, should we apply the same regularization coefficient to the bright centre and faint outskirts?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "First, there is a second limitation to understand. Even with enough mesh points, should we apply the same regularization coefficient to the bright centre and faint outskirts?\n", + "\n", "__Why one regularization coefficient becomes a compromise__\n", "\n", "Suppose we had enough mesh points to resolve the galaxy\u2019s bright centre. Would that solve the problem?\n", @@ -838,13 +788,8 @@ "\n", "These changes need not be equally visible in every dataset. The important point is that changing one coefficient changes the smoothing preference everywhere, even though different galaxy regions may benefit from different strengths.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Why maximizing the evidence does not remove the compromise__\n", "\n", "Why does the Bayesian evidence not simply select a coefficient that fixes both regions?\n", @@ -894,13 +839,8 @@ "\n", "The evidence still decides whether that additional flexibility is useful. We compare the constant and adaptive schemes on the same dataset, allowing their parameters to vary appropriately. Adaptation is a way to improve the available reconstructions, rather than a guarantee that every fit will improve.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Wrap Up__\n", "\n", "We began with three galaxies whose light became progressively more concentrated, while keeping the image sampling, PSF and noise realization fixed.\n", @@ -922,13 +862,8 @@ "\n", "At each stage, we will return to the questions raised here: does the mesh resolve the galaxy\u2019s bright structure, and does regularization preserve that structure while controlling fluctuations elsewhere?\n", "\n", - "Tutorial 5 then returns to search chaining and combines an MGE with a pixelization. That alternative can let analytic profiles describe the smooth central light while a mesh supplies additional spatial freedom." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "Tutorial 5 then returns to search chaining and combines an MGE with a pixelization. That alternative can let analytic profiles describe the smooth central light while a mesh supplies additional spatial freedom.\n", + "\n", "**\ud83e\udd16 Ask AI:** How would you distinguish insufficient galaxy-mesh resolution from over-smoothing when compact-galaxy residuals remain at the evidence-preferred coefficient?" ] } diff --git a/notebooks/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.ipynb b/notebooks/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.ipynb index 0244bdf..e67ef96 100644 --- a/notebooks/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.ipynb +++ b/notebooks/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.ipynb @@ -29,51 +29,8 @@ "- Controlling the transition with `signal_scale`\n", "- Exploring the adaptive coefficients\n", "- Does adaptive regularization address the fit problem?\n", - "- Wrap Up" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__Google Colab Setup__\n", - "\n", - "Set up Google Colab as in [the introductory notebook](https://github.com/PyAutoLabs/HowToGalaxy/blob/main/notebooks/chapter_1_introduction/tutorial_1_grids_and_galaxies.ipynb).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "cellView": "form", - "jupyter": { - "source_hidden": true - } - }, - "outputs": [], - "source": [ - "# @title Set up Google Colab { display-mode: \"form\" }\n", - "try:\n", - " import google.colab\n", - "except ImportError:\n", - " from autogalaxy import setup_colab as _setup_colab\n", - "else:\n", - " import importlib\n", - " import subprocess\n", - " import sys\n", - "\n", - " subprocess.check_call(\n", - " [sys.executable, \"-m\", \"pip\", \"install\", \"autonerves\", \"--no-deps\"]\n", - " )\n", - " _setup_colab = importlib.import_module(\"autonerves.setup_colab\")\n", + "- Wrap Up\n", "\n", - "_setup_colab.setup(\"howtogalaxy\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ "__Adaptive galaxy reconstruction__\n", "\n", "In **Fit Problems**, we identified two limitations of our reconstruction: too few mesh points across compact galaxy structure, and a single regularization coefficient that must compromise between the bright centre and faint outskirts.\n", @@ -103,18 +60,51 @@ "- Comparing reconstructions on the same dataset.\n", "- Preparing for the combined analytic and pixelized model in Tutorial 5.\n", "\n", - "---" + "---\n", + "\n", + "__Returning to the compact-galaxy problem__\n", + "\n", + "We return to the very compact galaxy from **Fit Problems**. Keeping the same example lets us examine whether the adaptive methods address the difficulties we have just investigated.\n", + "\n", + "The setup below reproduces that dataset, including its PSF and Gaussian noise realization. This makes the tutorial runnable independently." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "__Returning to the compact-galaxy problem__\n", + "__Google Colab Setup__\n", "\n", - "We return to the very compact galaxy from **Fit Problems**. Keeping the same example lets us examine whether the adaptive methods address the difficulties we have just investigated.\n", + "Set up Google Colab as in [the introductory notebook](https://github.com/PyAutoLabs/HowToGalaxy/blob/main/notebooks/chapter_1_introduction/tutorial_1_grids_and_galaxies.ipynb).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "jupyter": { + "source_hidden": true + } + }, + "outputs": [], + "source": [ + "# @title Set up Google Colab { display-mode: \"form\" }\n", + "try:\n", + " import google.colab\n", + "except ImportError:\n", + " from autogalaxy import setup_colab as _setup_colab\n", + "else:\n", + " import importlib\n", + " import subprocess\n", + " import sys\n", "\n", - "The setup below reproduces that dataset, including its PSF and Gaussian noise realization. This makes the tutorial runnable independently." + " subprocess.check_call(\n", + " [sys.executable, \"-m\", \"pip\", \"install\", \"autonerves\", \"--no-deps\"]\n", + " )\n", + " _setup_colab = importlib.import_module(\"autonerves.setup_colab\")\n", + "\n", + "_setup_colab.setup(\"howtogalaxy\")" ] }, { @@ -210,13 +200,8 @@ "\n", "We know the simulated galaxy profile, but we will not use its brightness distribution to tell the adaptive mesh where to place its points. Brightness adaptation will use a fitted model image, as it would for observed data.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__From image coordinates to a reconstruction mesh__\n", "\n", "Previously, we constructed a rectangular mesh over the galaxy image.\n", @@ -261,20 +246,10 @@ "\n", "The overlay\u2019s shape describes the grid before masking. Its retained number of points is therefore smaller than `25 \u00d7 25` for our circular mask.\n", "\n", - "We will connect these coordinates directly into a triangulation." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The overlay still does not inspect brightness. Changing an extended galaxy into a compact one leaves these coordinates unchanged for a fixed mask. Switching triangulation alone therefore does not allocate extra resolution to the bright centre. We will establish a baseline reconstruction before introducing brightness-based placement." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "We will connect these coordinates directly into a triangulation.\n", + "\n", + "The overlay still does not inspect brightness. Changing an extended galaxy into a compact one leaves these coordinates unchanged for a fixed mask. Switching triangulation alone therefore does not allocate extra resolution to the bright centre. We will establish a baseline reconstruction before introducing brightness-based placement.\n", + "\n", "__Constructing the Delaunay galaxy mesh__\n", "\n", "We now connect the selected mesh points into a **Delaunay triangulation**.\n", @@ -350,13 +325,8 @@ "\n", "The coefficient of `1.0` is only a starting value. We should not judge whether this mesh improves the fit until we have explored its regularization.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Interpolating within a triangle__\n", "\n", "How does a triangular mesh predict the brightness at an image coordinate?\n", @@ -422,13 +392,8 @@ "\n", "Interpolation still does not determine the vertex brightnesses. Those are solved by the inversion, with regularization controlling how freely they can vary.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Regularization on an irregular mesh__\n", "\n", "We begin with the same `Constant` regularization scheme used earlier.\n", @@ -499,13 +464,8 @@ "\n", "We have changed the mesh geometry, but two limitations remain. The overlay does not respond to the galaxy brightness, and one coefficient still controls regularization everywhere.\n", "\n", - "Next, we will use a fitted image to guide where the image-mesh points are placed, concentrating more sampling on the galaxy emission." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "Next, we will use a fitted image to guide where the image-mesh points are placed, concentrating more sampling on the galaxy emission.\n", + "\n", "__Building an adapt image__\n", "\n", "Our overlay samples the image mask uniformly. It does not distinguish bright galaxy emission from background noise.\n", @@ -544,13 +504,8 @@ "\n", "We will keep this adapt image fixed while comparing mesh settings. It guides the placement of points; it does not fix the brightness values reconstructed on the new mesh.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Placing points with a Hilbert image mesh__\n", "\n", "We now replace the evenly spaced overlay with a **Hilbert image mesh**.\n", @@ -605,24 +560,14 @@ "\n", "The overlay distributes its points evenly across the image mask. The Hilbert mesh uses the adapt image to concentrate more points on the emission, while the non-zero weight floor retains some sampling in faint regions.\n", "\n", - "These selected sky coordinates will be the reconstruction vertices." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "These selected sky coordinates will be the reconstruction vertices.\n", + "\n", "The point distribution now responds to the fitted image brightness. As the galaxy becomes more compact, a brightness-weighted mesh can place more points across that compact emission. Its effective resolution remains limited by the image sampling, PSF and signal-to-noise; more vertices alone do not recover arbitrary small-scale structure.\n", "\n", "Next, let\u2019s examine how its weights are calculated.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Controlling the brightness weighting__\n", "\n", "Two parameters control how the adapt image becomes a weight map: `weight_power` and `weight_floor`.\n", @@ -694,13 +639,8 @@ "\n", "The weight floor helps moderate this effect. Here, every location has a weight of at least `0.05`. This is a minimum weight, not a statement that five per cent of the mesh points must lie in the background.\n", "\n", - "Next, we will vary that floor and reconstruct the galaxy with the Hilbert mesh, checking the residuals and evidence rather than judging the mesh by its appearance alone." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "Next, we will vary that floor and reconstruct the galaxy with the Hilbert mesh, checking the residuals and evidence rather than judging the mesh by its appearance alone.\n", + "\n", "__Keeping resolution in the faint regions__\n", "\n", "Increasing `weight_power` concentrates points on the brightest parts of the adapt image. However, the galaxy may also have faint extended emission that needs to be reconstructed.\n", @@ -766,13 +706,8 @@ "\n", "For our first reconstruction, we return to the mesh already constructed with `weight_power=1.0` and `weight_floor=0.05`. These are starting choices to investigate, rather than settings we have established as optimal.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Reconstructing with the Hilbert mesh__\n", "\n", "We now use the Hilbert coordinates to build a Delaunay galaxy mesh.\n", @@ -849,13 +784,8 @@ "\n", "We have initially reused the overlay\u2019s preferred coefficient. As tutorial 2 showed, changing the mesh can change the preferred smoothing strength. We therefore need to explore regularization again before comparing the two reconstructions.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Comparing overlay and Hilbert reconstructions__\n", "\n", "Let\u2019s scan the regularization coefficient for the Hilbert mesh, using the same range as the overlay.\n", @@ -958,13 +888,8 @@ "\n", "This tests one Hilbert weighting choice, using a fixed adapt image. It does not establish that every Hilbert mesh outperforms every overlay.\n", "\n", - "We have now addressed where the galaxy points are placed. Next, we will address how to regularize their brightnesses on an irregular mesh, before allowing the smoothing strength to vary between bright and faint regions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "We have now addressed where the galaxy points are placed. Next, we will address how to regularize their brightnesses on an irregular mesh, before allowing the smoothing strength to vary between bright and faint regions.\n", + "\n", "__Smoothing on an irregular mesh__\n", "\n", "Our Delaunay mesh has vertices with different neighbour counts, edge lengths and directions.\n", @@ -986,13 +911,8 @@ "\n", "We will first examine `ConstantSplit`, then introduce the brightness-dependent coefficients.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Reconstructing with ConstantSplit__\n", "\n", "Let\u2019s keep the Hilbert mesh and adapt image fixed and change the regularization scheme.\n", @@ -1096,13 +1016,8 @@ "\n", "Split changes how local brightness variations are penalized, but `ConstantSplit` still applies one coefficient everywhere. It therefore retains the centre-versus-outskirts compromise identified in **Fit Problems**.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Allowing different smoothing strengths__\n", "\n", "We now let the regularization strength depend on the galaxy brightness.\n", @@ -1177,13 +1092,8 @@ "\n", "These weights control the regularization penalty; they are not uncertainties on the reconstructed brightnesses.\n", "\n", - "The trial coefficients were chosen to illustrate the mechanism. We have not yet established that they improve the fit or maximize the evidence. Next, we will examine the transition controlled by `signal_scale` and explore the adaptive coefficients systematically." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "The trial coefficients were chosen to illustrate the mechanism. We have not yet established that they improve the fit or maximize the evidence. Next, we will examine the transition controlled by `signal_scale` and explore the adaptive coefficients systematically.\n", + "\n", "__Controlling the transition with `signal_scale`__\n", "\n", "The inner and outer coefficients set the smoothing strengths at the high- and low-signal ends of the galaxy. How do we assign a strength to the regions between them?\n", @@ -1248,13 +1158,8 @@ "\n", "Also distinguish `signal_scale` from the Hilbert mesh\u2019s `weight_power`. Both transform brightness-derived information, but they control different things: `weight_power` changes **where mesh points are placed**, whereas `signal_scale` changes **how their brightnesses are regularized**.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Exploring the adaptive coefficients__\n", "\n", "We now have three regularization parameters: the inner coefficient, outer coefficient and signal scale.\n", @@ -1336,13 +1241,8 @@ "\n", "For a complete analysis, a non-linear search can explore these regularization parameters. Tutorial 5 demonstrates search chaining for a combined MGE\u2013pixelization model, using constant regularization to isolate the component-decomposition question.\n", "\n", - "---" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "---\n", + "\n", "__Does adaptive regularization address the fit problem?__\n", "\n", "Let\u2019s inspect the highest-evidence adaptive reconstruction we have evaluated and compare it with `ConstantSplit`.\n", @@ -1434,13 +1334,8 @@ "\n", "If substantial residuals remain, inspect where they occur. Adaptive regularization still cannot supply resolution missing from the mesh, and both adaptive steps depend on the initial adapt image.\n", "\n", - "We have now explored the mesh placement and smoothing separately. Next, Tutorial 5 explores a complementary strategy: fitting smooth light with an MGE and additional light with a pixelization. This can reduce the burden on the mesh, but makes the interpretation of individual components depend on how their shared light is divided." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ + "We have now explored the mesh placement and smoothing separately. Next, Tutorial 5 explores a complementary strategy: fitting smooth light with an MGE and additional light with a pixelization. This can reduce the burden on the mesh, but makes the interpretation of individual components depend on how their shared light is divided.\n", + "\n", "__Wrap Up__\n", "\n", "We have separated two choices that a single regularization coefficient cannot make: where the mesh has resolution,\n", diff --git a/scripts/chapter_1_introduction/tutorial_0_visualization.py b/scripts/chapter_1_introduction/tutorial_0_visualization.py index 504dbdb..4402d34 100644 --- a/scripts/chapter_1_introduction/tutorial_0_visualization.py +++ b/scripts/chapter_1_introduction/tutorial_0_visualization.py @@ -134,9 +134,7 @@ **🤖 Ask AI:** Why can logarithmic colour scaling make faint structure easier to see without increasing its signal-to-noise ratio? -""" -""" __Visuals__ A mask selects which pixels to use. Here an annular mask keeps a ring between 0.3 and 3.0 arcseconds from @@ -159,9 +157,7 @@ """ Compare the masked plot with the original image: the central light is excluded from this view, not removed from the original dataset. We keep the masked version in `masked_dataset` so `dataset` remains available. -""" -""" __Wrap Up__ You have plotted an image, compared dataset panels and changed the display without changing the pixel values. diff --git a/scripts/chapter_3_pixelizations/tutorial_3_fit_problems.py b/scripts/chapter_3_pixelizations/tutorial_3_fit_problems.py index a90054e..cdd6f31 100644 --- a/scripts/chapter_3_pixelizations/tutorial_3_fit_problems.py +++ b/scripts/chapter_3_pixelizations/tutorial_3_fit_problems.py @@ -19,9 +19,6 @@ - Why maximizing the evidence does not remove the compromise - Wrap Up -""" - -r""" __When the best coefficient is not enough__ We have learned how to reconstruct a galaxy and choose its regularization coefficient using Bayesian evidence. @@ -54,9 +51,7 @@ - Motivating adaptation to the galaxy’s brightness distribution. --- -""" -r""" __Three progressively compact galaxies__ We use three Sérsic profiles with the same centre and elliptical shape. @@ -106,9 +101,7 @@ There is no lensing transformation. All three images use the same sky coordinates, while the spatial resolution needed to describe their light changes. --- -""" -r""" __Simulating the images__ We now simulate the three galaxy images using the same image grid and telescope blurring. @@ -205,9 +198,7 @@ Next, we will reconstruct them using the same rectangular mesh and constant regularization scheme. For each dataset, we will scan the coefficient and inspect its evidence-preferred reconstruction. We will compare alternative reconstructions **within each dataset**. We will not rank the three different simulated galaxies against one another using their absolute evidence values. -""" -r""" __Reconstructing the galaxies__ We will reconstruct all three galaxies using a `25 × 25` rectangular mesh and `Constant` regularization. @@ -246,9 +237,7 @@ def fit_source(dataset, coefficient): For now, the only reconstruction setting we vary is the regularization coefficient. --- -""" -r""" __Finding the preferred regularization__ As in tutorial 2, we evaluate a range of coefficients and compare their log evidences. We do this separately for each dataset: a coefficient suitable for the extended galaxy need not be suitable for either compact galaxy. @@ -332,9 +321,7 @@ def fit_source(dataset, coefficient): We can now inspect the reconstructions knowing that we have selected their smoothing strengths systematically. --- -""" -r""" __Starting with the extended galaxy__ Let’s begin with the extended galaxy. @@ -385,9 +372,7 @@ def fit_source(dataset, coefficient): A value around one is a useful reference for noise-level residuals, but it does not tell us whether those residuals form a spatial pattern. Keep the residual map alongside this number. This extended-galaxy fit provides our baseline. Next, we will make the galaxy more compact without giving the mesh any additional resolution, and examine where the reconstruction begins to struggle. -""" -r""" __Making the galaxy more compact__ Now inspect the compact galaxy. @@ -436,9 +421,7 @@ def fit_source(dataset, coefficient): The question is therefore no longer simply “Have we chosen the wrong coefficient?” We need to ask whether our mesh and regularization scheme can represent this galaxy adequately. --- -""" -r""" __A very compact galaxy__ Our final galaxy has an effective radius of just `0.1` arcsec and a Sérsic index of `4.0`. Its light rises steeply towards the centre, placing a greater demand on the reconstruction. @@ -495,9 +478,7 @@ def fit_source(dataset, coefficient): These galaxies also have different brightness distributions and signal-to-noise ratios. We should not interpret the comparison as a measurement of galaxy-size effects alone. Its purpose is to expose the practical difficulty of reconstructing increasingly concentrated light with an unchanged mesh and one smoothing coefficient. --- -""" -r""" __Why the mesh becomes a limitation__ Let’s examine the first problem: where our galaxy pixels are placed. @@ -540,9 +521,7 @@ def fit_source(dataset, coefficient): This motivates adapting the mesh to the **galaxy’s brightness distribution**, which we will explore in the next tutorial. First, there is a second limitation to understand. Even with enough mesh points, should we apply the same regularization coefficient to the bright centre and faint outskirts? -""" -r""" __Why one regularization coefficient becomes a compromise__ Suppose we had enough mesh points to resolve the galaxy’s bright centre. Would that solve the problem? @@ -616,9 +595,7 @@ def fit_source(dataset, coefficient): These changes need not be equally visible in every dataset. The important point is that changing one coefficient changes the smoothing preference everywhere, even though different galaxy regions may benefit from different strengths. --- -""" -r""" __Why maximizing the evidence does not remove the compromise__ Why does the Bayesian evidence not simply select a coefficient that fixes both regions? @@ -658,9 +635,7 @@ def fit_source(dataset, coefficient): The evidence still decides whether that additional flexibility is useful. We compare the constant and adaptive schemes on the same dataset, allowing their parameters to vary appropriately. Adaptation is a way to improve the available reconstructions, rather than a guarantee that every fit will improve. --- -""" -r""" __Wrap Up__ We began with three galaxies whose light became progressively more concentrated, while keeping the image sampling, PSF and noise realization fixed. @@ -683,9 +658,7 @@ def fit_source(dataset, coefficient): At each stage, we will return to the questions raised here: does the mesh resolve the galaxy’s bright structure, and does regularization preserve that structure while controlling fluctuations elsewhere? Tutorial 5 then returns to search chaining and combines an MGE with a pixelization. That alternative can let analytic profiles describe the smooth central light while a mesh supplies additional spatial freedom. -""" -r""" **🤖 Ask AI:** How would you distinguish insufficient galaxy-mesh resolution from over-smoothing when compact-galaxy residuals remain at the evidence-preferred coefficient? __Env__ diff --git a/scripts/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.py b/scripts/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.py index b8f066d..197c600 100644 --- a/scripts/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.py +++ b/scripts/chapter_3_pixelizations/tutorial_4_adaptive_reconstruction.py @@ -26,9 +26,6 @@ - Does adaptive regularization address the fit problem? - Wrap Up -""" - -r""" __Adaptive galaxy reconstruction__ In **Fit Problems**, we identified two limitations of our reconstruction: too few mesh points across compact galaxy structure, and a single regularization coefficient that must compromise between the bright centre and faint outskirts. @@ -59,9 +56,7 @@ - Preparing for the combined analytic and pixelized model in Tutorial 5. --- -""" -r""" __Returning to the compact-galaxy problem__ We return to the very compact galaxy from **Fit Problems**. Keeping the same example lets us examine whether the adaptive methods address the difficulties we have just investigated. @@ -152,9 +147,7 @@ We know the simulated galaxy profile, but we will not use its brightness distribution to tell the adaptive mesh where to place its points. Brightness adaptation will use a fitted model image, as it would for observed data. --- -""" -r""" __From image coordinates to a reconstruction mesh__ Previously, we constructed a rectangular mesh over the galaxy image. @@ -189,13 +182,9 @@ The overlay’s shape describes the grid before masking. Its retained number of points is therefore smaller than `25 × 25` for our circular mask. We will connect these coordinates directly into a triangulation. -""" -r""" The overlay still does not inspect brightness. Changing an extended galaxy into a compact one leaves these coordinates unchanged for a fixed mask. Switching triangulation alone therefore does not allocate extra resolution to the bright centre. We will establish a baseline reconstruction before introducing brightness-based placement. -""" -r""" __Constructing the Delaunay galaxy mesh__ We now connect the selected mesh points into a **Delaunay triangulation**. @@ -261,9 +250,7 @@ def fit_delaunay_overlay(coefficient): The coefficient of `1.0` is only a starting value. We should not judge whether this mesh improves the fit until we have explored its regularization. --- -""" -r""" __Interpolating within a triangle__ How does a triangular mesh predict the brightness at an image coordinate? @@ -319,9 +306,7 @@ def fit_delaunay_overlay(coefficient): Interpolation still does not determine the vertex brightnesses. Those are solved by the inversion, with regularization controlling how freely they can vary. --- -""" -r""" __Regularization on an irregular mesh__ We begin with the same `Constant` regularization scheme used earlier. @@ -383,9 +368,7 @@ def fit_delaunay_overlay(coefficient): We have changed the mesh geometry, but two limitations remain. The overlay does not respond to the galaxy brightness, and one coefficient still controls regularization everywhere. Next, we will use a fitted image to guide where the image-mesh points are placed, concentrating more sampling on the galaxy emission. -""" -r""" __Building an adapt image__ Our overlay samples the image mask uniformly. It does not distinguish bright galaxy emission from background noise. @@ -414,9 +397,7 @@ def fit_delaunay_overlay(coefficient): We will keep this adapt image fixed while comparing mesh settings. It guides the placement of points; it does not fix the brightness values reconstructed on the new mesh. --- -""" -r""" __Placing points with a Hilbert image mesh__ We now replace the evenly spaced overlay with a **Hilbert image mesh**. @@ -461,17 +442,13 @@ def fit_delaunay_overlay(coefficient): The overlay distributes its points evenly across the image mask. The Hilbert mesh uses the adapt image to concentrate more points on the emission, while the non-zero weight floor retains some sampling in faint regions. These selected sky coordinates will be the reconstruction vertices. -""" -r""" The point distribution now responds to the fitted image brightness. As the galaxy becomes more compact, a brightness-weighted mesh can place more points across that compact emission. Its effective resolution remains limited by the image sampling, PSF and signal-to-noise; more vertices alone do not recover arbitrary small-scale structure. Next, let’s examine how its weights are calculated. --- -""" -r""" __Controlling the brightness weighting__ Two parameters control how the adapt image becomes a weight map: `weight_power` and `weight_floor`. @@ -533,9 +510,7 @@ def fit_delaunay_overlay(coefficient): The weight floor helps moderate this effect. Here, every location has a weight of at least `0.05`. This is a minimum weight, not a statement that five per cent of the mesh points must lie in the background. Next, we will vary that floor and reconstruct the galaxy with the Hilbert mesh, checking the residuals and evidence rather than judging the mesh by its appearance alone. -""" -r""" __Keeping resolution in the faint regions__ Increasing `weight_power` concentrates points on the brightest parts of the adapt image. However, the galaxy may also have faint extended emission that needs to be reconstructed. @@ -591,9 +566,7 @@ def fit_delaunay_overlay(coefficient): For our first reconstruction, we return to the mesh already constructed with `weight_power=1.0` and `weight_floor=0.05`. These are starting choices to investigate, rather than settings we have established as optimal. --- -""" -r""" __Reconstructing with the Hilbert mesh__ We now use the Hilbert coordinates to build a Delaunay galaxy mesh. @@ -660,9 +633,7 @@ def fit_delaunay_hilbert(coefficient): We have initially reused the overlay’s preferred coefficient. As tutorial 2 showed, changing the mesh can change the preferred smoothing strength. We therefore need to explore regularization again before comparing the two reconstructions. --- -""" -r""" __Comparing overlay and Hilbert reconstructions__ Let’s scan the regularization coefficient for the Hilbert mesh, using the same range as the overlay. @@ -744,9 +715,7 @@ def fit_delaunay_hilbert(coefficient): This tests one Hilbert weighting choice, using a fixed adapt image. It does not establish that every Hilbert mesh outperforms every overlay. We have now addressed where the galaxy points are placed. Next, we will address how to regularize their brightnesses on an irregular mesh, before allowing the smoothing strength to vary between bright and faint regions. -""" -r""" __Smoothing on an irregular mesh__ Our Delaunay mesh has vertices with different neighbour counts, edge lengths and directions. @@ -769,9 +738,7 @@ def fit_delaunay_hilbert(coefficient): We will first examine `ConstantSplit`, then introduce the brightness-dependent coefficients. --- -""" -r""" __Reconstructing with ConstantSplit__ Let’s keep the Hilbert mesh and adapt image fixed and change the regularization scheme. @@ -854,9 +821,7 @@ def fit_hilbert_with_regularization(regularization): Split changes how local brightness variations are penalized, but `ConstantSplit` still applies one coefficient everywhere. It therefore retains the centre-versus-outskirts compromise identified in **Fit Problems**. --- -""" -r""" __Allowing different smoothing strengths__ We now let the regularization strength depend on the galaxy brightness. @@ -921,9 +886,7 @@ def fit_hilbert_with_regularization(regularization): These weights control the regularization penalty; they are not uncertainties on the reconstructed brightnesses. The trial coefficients were chosen to illustrate the mechanism. We have not yet established that they improve the fit or maximize the evidence. Next, we will examine the transition controlled by `signal_scale` and explore the adaptive coefficients systematically. -""" -r""" __Controlling the transition with `signal_scale`__ The inner and outer coefficients set the smoothing strengths at the high- and low-signal ends of the galaxy. How do we assign a strength to the regions between them? @@ -978,9 +941,7 @@ def fit_hilbert_with_regularization(regularization): Also distinguish `signal_scale` from the Hilbert mesh’s `weight_power`. Both transform brightness-derived information, but they control different things: `weight_power` changes **where mesh points are placed**, whereas `signal_scale` changes **how their brightnesses are regularized**. --- -""" -r""" __Exploring the adaptive coefficients__ We now have three regularization parameters: the inner coefficient, outer coefficient and signal scale. @@ -1052,9 +1013,7 @@ def fit_hilbert_with_regularization(regularization): For a complete analysis, a non-linear search can explore these regularization parameters. Tutorial 5 demonstrates search chaining for a combined MGE–pixelization model, using constant regularization to isolate the component-decomposition question. --- -""" -r""" __Does adaptive regularization address the fit problem?__ Let’s inspect the highest-evidence adaptive reconstruction we have evaluated and compare it with `ConstantSplit`. @@ -1125,9 +1084,7 @@ def fit_hilbert_with_regularization(regularization): If substantial residuals remain, inspect where they occur. Adaptive regularization still cannot supply resolution missing from the mesh, and both adaptive steps depend on the initial adapt image. We have now explored the mesh placement and smoothing separately. Next, Tutorial 5 explores a complementary strategy: fitting smooth light with an MGE and additional light with a pixelization. This can reduce the burden on the mesh, but makes the interpretation of individual components depend on how their shared light is divided. -""" -r""" __Wrap Up__ We have separated two choices that a single regularization coefficient cannot make: where the mesh has resolution,