Skip to content

Commit c760348

Browse files
Jammy2211claude
authored andcommitted
Re-render tutorial_1 + tutorial_2 markdown pages after truncation restore
These two chapter-1 pages were rendered (batch 2b, #25) from the truncated scripts; #27 restored the scripts' full content, so the pages were stale/cut off. Regenerated from the restored scripts — now complete with all plots. markdown/ only; no scripts/ changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyqcbXuZvGVTHHEWhoEWkC
1 parent e9c791c commit c760348

20 files changed

Lines changed: 636 additions & 2 deletions

markdown/chapter_1_introduction/tutorial_1_grids_and_galaxies.md

Lines changed: 361 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ __Contents__
5858
- **Geometry:** The above grid is centered on the origin (0.0", 0.0").
5959
- **Light Profiles:** Galaxies are collections of stars, gas, dust, and other astronomical objects that emit light.
6060
- **One Dimension Projection:** We often want to calculative 1D quantities of a light profile, for example to plot how its light.
61+
- **Galaxies:** Galaxies are collections of light profiles that represent a galaxy's luminous emission.
62+
- **Units:** By assuming a redshift for a galaxy we can convert its quantities from arcseconds to kiloparsecs.
6163

6264

6365
```python
@@ -74,6 +76,12 @@ import autolens as al
7476
import autolens.plot as aplt
7577
```
7678

79+
2026-07-11 18:13:08,002 - matplotlib.font_manager - INFO - Failed to extract font properties from /usr/share/fonts/truetype/noto/NotoColorEmoji.ttf: Can not load face (unknown file format; error code 0x2)
80+
81+
82+
2026-07-11 18:13:08,198 - matplotlib.font_manager - INFO - generated new fontManager
83+
84+
7785
Working Directory has been set to `HowToLens`
7886

7987

@@ -566,10 +574,362 @@ plt.close()
566574
Since galaxy light distributions often cover a wide range of values, they are typically better visualized on a log10
567575
scale. This approach helps highlight details in the faint outskirts of a light profile.
568576

569-
The `plot_array`/`subplot_\*` object has a `use_log10` option that applies this transformation automatically. Below, you can see
577+
The `plot_array`/`subplot_\*` object has a `use_log10` option that applies this transformation automatically. Below, you can see
570578
that the image plotted in log10 space reveals more details.
571579

572580

581+
```python
582+
aplt.plot_array(
583+
array=sersic_light_profile.image_2d_from(grid=grid),
584+
title="Sersic Image",
585+
use_log10=True,
586+
)
587+
```
588+
589+
590+
591+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_45_0.png)
592+
593+
594+
595+
__Galaxies__
596+
597+
Now, let's introduce `Galaxy` objects, which are a key component in **PyAutoLens**.
598+
599+
A light profile represents a single feature of a galaxy, such as its bulge or disk. To model a complete galaxy,
600+
we combine multiple light profiles into a `Galaxy` object. This allows us to create images that include different
601+
components of a galaxy.
602+
603+
In addition to light profiles, a `Galaxy` has a `redshift`, which indicates how far away it is from Earth. The redshift
604+
is essential for performing unit conversions using cosmological calculations, such as converting arc-seconds into
605+
kiloparsecs. (A kiloparsec is a distance unit in astronomy, equal to about 3.26 million light-years.)
606+
607+
Redshifts are especially important in strong lensing, where the foreground lens galaxy and background source galaxy
608+
lie at two different redshifts. We are not yet performing any lensing calculations in this tutorial, so for now we
609+
simply use a single galaxy to build up intuition for the `Galaxy` object.
610+
611+
Let's start by creating a galaxy with two `Sersic` light profiles, which we will consider to represent a bulge and
612+
disk component of the galaxy, the two most important structures seen in galaxies.
613+
614+
615+
```python
616+
bulge = al.lp.Sersic(
617+
centre=(0.0, 0.0),
618+
ell_comps=(0.0, 0.111111),
619+
intensity=1.0,
620+
effective_radius=1.0,
621+
sersic_index=2.5,
622+
)
623+
624+
disk = al.lp.Sersic(
625+
centre=(0.0, 0.0),
626+
ell_comps=(0.0, 0.3),
627+
intensity=0.3,
628+
effective_radius=3.0,
629+
sersic_index=1.0,
630+
)
631+
632+
galaxy = al.Galaxy(redshift=0.5, bulge=bulge, disk=disk)
633+
634+
print(galaxy)
635+
```
636+
637+
Redshift: 0.5
638+
Light Profiles:
639+
Sersic
640+
centre: (0.0, 0.0)
641+
ell_comps: (0.0, 0.111111)
642+
intensity: 1.0
643+
effective_radius: 1.0
644+
sersic_index: 2.5
645+
Sersic
646+
centre: (0.0, 0.0)
647+
ell_comps: (0.0, 0.3)
648+
intensity: 0.3
649+
effective_radius: 3.0
650+
sersic_index: 1.0
651+
652+
653+
We can pass a 2D grid to a light profile to compute its image using the `image_2d_from` method.
654+
655+
The same approach works for a `Galaxy` object:
656+
657+
658+
```python
659+
image = galaxy.image_2d_from(grid=grid)
660+
661+
print("Intensity of `Grid2D` pixel 0:")
662+
print(image.native[0, 0])
663+
print("Intensity of `Grid2D` pixel 1:")
664+
print(image.native[0, 1])
665+
print("Intensity of `Grid2D` pixel 2:")
666+
print(image.native[0, 2])
667+
print("...")
668+
```
669+
670+
Intensity of `Grid2D` pixel 0:
671+
0.024894917164848044
672+
Intensity of `Grid2D` pixel 1:
673+
0.025428546280541572
674+
Intensity of `Grid2D` pixel 2:
675+
0.02596640780160061
676+
...
677+
678+
679+
We can plot the galaxy's image, just like how we did for a light profile.
680+
681+
682+
```python
683+
aplt.plot_array(array=galaxy.image_2d_from(grid=grid), title="Galaxy Bulge+Disk Image")
684+
```
685+
686+
687+
688+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_51_0.png)
689+
690+
691+
692+
The bulge dominates the center of the image, and is pretty much the only luminous emission we can see on a linear
693+
scale. The disk's emission is present, but it is much fainter and spread over a larger area.
694+
695+
We can confirm this using the `subplot_galaxy_light_profiles` method, which plots each individual light profile
696+
separately.
697+
698+
699+
```python
700+
aplt.subplot_galaxy_light_profiles(galaxy=galaxy, grid=grid)
701+
```
702+
703+
704+
705+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_53_0.png)
706+
707+
708+
709+
Because galaxy light distributions often follow a log10 pattern, plotting in log10 space helps reveal details in the
710+
outskirts of the light profile, in this case the emission of the disk.
711+
712+
This is especially helpful to separate the bulge and disk profiles, which have different intensities and sizes.
713+
714+
715+
```python
716+
aplt.plot_array(
717+
array=galaxy.image_2d_from(grid=grid),
718+
title="Galaxy Bulge+Disk Image",
719+
use_log10=True,
720+
)
721+
```
722+
723+
724+
725+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_55_0.png)
726+
727+
728+
729+
Using the tools above, we can visualize each light profile's contribution in 1D.
730+
731+
1D plots show the intensity of the light profile as a function of distance from the profile's center. The bulge
732+
and disk profiles in this example share the same `centre`, meaning that plotting them together on the same 1D plot
733+
shows how they vary relative to one another.
734+
735+
If the `centre` of the profiles were different, when you make the 1D plot you would need to decide whether to plot the
736+
profiles offset from one another or plot them both from zero.
737+
738+
739+
```python
740+
grid_2d_projected = grid.grid_2d_radial_projected_from(
741+
centre=galaxy.bulge.centre, angle=galaxy.bulge.angle()
742+
)
743+
bulge_image_1d = galaxy.bulge.image_2d_from(grid=grid_2d_projected)
744+
745+
grid_2d_projected = grid.grid_2d_radial_projected_from(
746+
centre=galaxy.disk.centre, angle=galaxy.disk.angle()
747+
)
748+
disk_image_1d = galaxy.disk.image_2d_from(grid=grid_2d_projected)
749+
750+
plt.plot(grid_2d_projected[:, 1], bulge_image_1d, label="Bulge")
751+
plt.plot(grid_2d_projected[:, 1], disk_image_1d, label="Disk")
752+
plt.xlabel("Radius (arcseconds)")
753+
plt.ylabel("Luminosity")
754+
plt.legend()
755+
plt.show()
756+
plt.close()
757+
```
758+
759+
760+
761+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_57_0.png)
762+
763+
764+
765+
We can group multiple galaxies at the same redshift into a `Galaxies` object, which is created from a list of
766+
individual galaxies.
767+
768+
In a strong lens, we ultimately group together a foreground lens galaxy and a background source galaxy. For now, we
769+
simply create a second galaxy and combine it with the original galaxy into a `Galaxies` object, to see how the light
770+
of multiple galaxies is represented.
771+
772+
773+
```python
774+
extra_galaxy = al.Galaxy(
775+
redshift=0.5,
776+
bulge=al.lp.Sersic(
777+
centre=(0.2, 0.3),
778+
ell_comps=(0.0, 0.111111),
779+
intensity=1.0,
780+
effective_radius=1.0,
781+
sersic_index=2.5,
782+
),
783+
)
784+
785+
galaxies = al.Galaxies(galaxies=[galaxy, extra_galaxy])
786+
```
787+
788+
The `Galaxies` object has similar methods to those for light profiles and individual galaxies.
789+
790+
For example, `image_2d_from` sums the images of all the galaxies.
791+
792+
793+
```python
794+
image = galaxies.image_2d_from(grid=grid)
795+
```
796+
797+
We can plot the combined image of all the galaxies, just like with other plotters.
798+
799+
800+
```python
801+
aplt.plot_array(array=galaxies.image_2d_from(grid=grid), title="Image")
802+
```
803+
804+
805+
806+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_63_0.png)
807+
808+
809+
810+
A subplot of each individual galaxy image can also be created.
811+
812+
813+
```python
814+
aplt.subplot_galaxies(galaxies=galaxies, grid=grid)
815+
```
816+
817+
818+
819+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_65_0.png)
820+
821+
822+
823+
Because galaxy light distributions often follow a log10 pattern, plotting in log10 space helps reveal details in the
824+
outskirts of the light profile.
825+
826+
This is especially helpful when visualizing how multiple galaxies overlap.
827+
828+
829+
```python
830+
aplt.plot_array(array=galaxies.image_2d_from(grid=grid), title="Image", use_log10=True)
831+
```
832+
833+
834+
835+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_67_0.png)
836+
837+
838+
839+
__Units__
840+
841+
Earlier, we mentioned that a galaxy's `redshift` allows us to convert between arcseconds and kiloparsecs.
842+
843+
A redshift measures how much a galaxy's light is stretched by the Universe's expansion. A higher redshift means the
844+
galaxy is further away, and its light has been stretched more. By knowing a galaxy's redshift, we can convert angular
845+
distances (like arcseconds) to physical distances (like kiloparsecs).
846+
847+
To perform this conversion, we use a cosmological model that describes the Universe's expansion. Below, we use
848+
the `Planck15` cosmology, which is based on observations from the Planck satellite.
849+
850+
851+
```python
852+
cosmology = al.cosmo.Planck15()
853+
854+
kpc_per_arcsec = cosmology.kpc_per_arcsec_from(redshift=galaxy.redshift)
855+
856+
print("Kiloparsecs per Arcsecond:")
857+
print(kpc_per_arcsec)
858+
```
859+
860+
Kiloparsecs per Arcsecond:
861+
6.288247910157764
862+
863+
864+
This `kpc_per_arcsec` can be used as a conversion factor between arcseconds and kiloparsecs when plotting images of
865+
galaxies.
866+
867+
We compute this value and plot the image, which by default is shown in units of arcseconds.
868+
869+
870+
```python
871+
aplt.plot_array(array=galaxy.image_2d_from(grid=grid), title="Image")
872+
```
873+
874+
875+
876+
![png](tutorial_1_grids_and_galaxies_files/tutorial_1_grids_and_galaxies_71_0.png)
877+
878+
879+
880+
__Wrap Up__
881+
882+
In this tutorial, you've learnt the basic quantities used to describe the galaxies that make up a strong lens, before
883+
we introduce any lensing calculations.
884+
885+
Let's summarise what we've covered:
886+
887+
- **Grids**: A grid is a set of 2D $(y,x)$ coordinates that represent the positions where we measure the light of a
888+
galaxy.
889+
890+
- **Geometry**: We showed how to shift, rotate, and convert grids to elliptical coordinates.
891+
892+
- **Light Profiles**: Light profiles are analytic functions that describe how a galaxy's light is distributed in
893+
space. We used the `Sersic` profile to create images of galaxies.
894+
895+
- **Galaxies**: Galaxies are collections of light profiles. We created galaxies with multiple light profiles, combined
896+
them into a `Galaxies` object, and visualized their images.
897+
898+
- **Units**: By assuming redshifts for galaxies we can convert their quantities from arcseconds to physical units like
899+
kiloparsecs.
900+
901+
In the next tutorial, we'll introduce the mass of a galaxy and perform our first lensing calculation, whereby the
902+
light of a background source galaxy is deflected by the mass of a foreground lens galaxy.
903+
904+
__Advanced Topics__
905+
906+
The following advanced topics are not important for a new user learning the software for the first time. However,
907+
once you are an expert user, the following guides and concepts are important for doing accurate strong lens analysis,
908+
and thus may be things you want to commit to memory as future references.
909+
910+
__Other Unit Conversion__
911+
912+
Above, we used a redshift to convert between arcseconds and kiloparsecs. This is just one example of a unit conversion
913+
that can be performed using a galaxy's redshift.
914+
915+
There are many other unit conversions that can be performed, such as converting the units of a galaxy's image to what
916+
Astronomers call an AB magnitude system, which is a system used to measure the brightness of galaxies.
917+
918+
The `autolens_workspace/*/guides/units` module contains many examples of unit conversions and how to use them,
919+
but they will not be covered in the *HowToLens* tutorials.
920+
921+
__Over Sampling__
922+
923+
Over sampling is a numerical technique where the images of light profiles and galaxies are evaluated
924+
on a higher resolution grid than the image data to ensure the calculation is accurate.
925+
926+
For a new user, the details of over-sampling are not important, therefore just be aware that all calculations use an
927+
adaptive over sampling scheme with high accuracy across all use cases.
928+
929+
Once you are more experienced, you should read up on over-sampling in more detail via
930+
the `autolens_workspace/*/guides/over_sampling.ipynb` notebook.
931+
932+
573933
```python
574934

575935
```
110 KB
Loading
30 KB
Loading
44.6 KB
Loading
85 KB
Loading
17.4 KB
Loading
25.3 KB
Loading
64.4 KB
Loading
84.5 KB
Loading
24.2 KB
Loading

0 commit comments

Comments
 (0)