@@ -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
7476import 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()
566574Since galaxy light distributions often cover a wide range of values, they are typically better visualized on a log10
567575scale. 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
570578that 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```
0 commit comments