""" __Mass Profiles__ **PyAutoLens** uses `MassProfile` objects to represent a galaxy's mass distribution and perform ray-tracing calculations. Below we create an `EllIsothermal` `MassProfile` and compute its deflection angles on our Cartesian grid: """ isothermal_mass_profile = al.mp.EllIsothermal(centre=(0.0, 0.0), elliptical_comps=(0.1, 0.0), einstein_radius=1.6) deflections = isothermal_mass_profile.deflections_yx_2d_from(grid=grid) """ Lets plot the `MassProfile`'s deflection angle map. """ mass_profile_plotter = aplt.MassProfilePlotter( mass_profile=isothermal_mass_profile, grid=grid) mass_profile_plotter.figures_2d(convergence=False, potential=False, deflections_y=True, deflections_x=True) """ The deflection angles describe how a given mass distribution deflects the light-rays of the source galaxy, allowing us create strong lens systems like the one shown above! __Galaxies__ A `Galaxy` object is a collection of `LightProfile` and `MassProfile` objects at a given redshift. The code below creates two galaxies representing the lens and source galaxies shown in the strong lensing diagram above. """ lens_galaxy = al.Galaxy(redshift=0.5, bulge=sersic_light_profile,
elliptical_comps=al.convert.elliptical_comps_from(axis_ratio=0.7, angle=45.0), slope=2.1, ) """ We also need the 2D grid the `MassProfile`'s are evaluated on. """ grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) """ We now pass the mass profiles and grid to a `MassProfilePlotter` and create a `MultiYX1DPlotter` which will be used to plot both of their convergences in 1D on the same figure. """ mat_plot_1d = aplt.MatPlot1D(yx_plot=aplt.YXPlot(plot_axis_type="semilogy")) mass_profile_plotter_0 = aplt.MassProfilePlotter(mass_profile=mass_0, grid=grid, mat_plot_1d=mat_plot_1d) mass_profile_plotter_1 = aplt.MassProfilePlotter(mass_profile=mass_1, grid=grid, mat_plot_1d=mat_plot_1d) """ We use these plotters to create a `MultiYX1DPlotter` which plot both of their convergences in 1D on the same figure. """ multi_plotter = aplt.MultiYX1DPlotter( plotter_list=[mass_profile_plotter_0, mass_profile_plotter_1]) """ We now use the multi plotter to plot the convergences, where: - `func_name`: he name of the `MassProfilePlotter` function we call, in this case `figures_1d`. - `figure_name`: the name of the function's boolean input we set to True such that it plots, in this case `convergence`.
""" mass = al.mp.EllIsothermal( centre=(0.0, 0.0), einstein_radius=1.6, elliptical_comps=al.convert.elliptical_comps_from(axis_ratio=0.7, angle=45.0), ) """ We also need the 2D grid the `MassProfile` is evaluated on. """ grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) """ We now pass the mass profile and grid to a `MassProfilePlotter` and call various `figure_*` methods to plot different attributes in 1D and 2D. """ mass_profile_plotter = aplt.MassProfilePlotter(mass_profile=mass, grid=grid) mass_profile_plotter.figures_2d( convergence=True, potential=True, deflections_y=True, deflections_x=True, magnification=True, ) mass_profile_plotter.figures_1d(convergence=True, potential=True) """ A `MassProfile` and its `Grid2D` contains the following attributes which can be plotted automatically via the `Include2D` object. (By default, a `Grid2D` does not contain a `Mask2D`, we therefore manually created a `Grid2D` with a mask to illustrate plotting its mask and border below). """
einstein_radius=1.0, ) """ We also need the 2D grid the `MassProfile` is evaluated on. """ grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) """ We now pass the mass profile and grid to a `MassProfilePlotter` and call the `figures_1d` methods to plot its convergence as a function of radius. The `MassProfile` includes the einstein radius as an internal property, meaning we can plot it via an `Include1D` object. """ include_1d = aplt.Include1D(einstein_radius=True) mass_profile_plotter = aplt.MassProfilePlotter(mass_profile=mass, grid=grid, include_1d=include_1d) mass_profile_plotter.figures_1d(convergence=True) """ The appearance of the einstein radius is customized using a `EinsteinRadiusAXVLine` object. To plot the einstein radius as a vertical line this wraps the following matplotlib method: plt.axvline: https://matplotlib.org/3.3.2/api/_as_gen/matplotlib.pyplot.axvline.html """ einstein_radius_axvline = aplt.EinsteinRadiusAXVLine(linestyle="-.", c="r", linewidth=20) mat_plot_1d = aplt.MatPlot1D(einstein_radius_axvline=einstein_radius_axvline)
(If you are still unclear what exactly a deflection angle means or how it will help us with gravitational lensing, things should become a lot clearer in tutorial 4 of this chapter. For now, just look at the pretty pictures they make!). """ mass_profile_deflections = sis_mass_profile.deflections_yx_2d_from(grid=grid) print("deflection-angles of `Grid2D` pixel 0:") print(mass_profile_deflections.native[0, 0]) print("deflection-angles of `Grid2D` pixel 1:") print(mass_profile_deflections.slim[1]) print() """ A `MassProfilePlotter` can plot the deflection angles. (The black and red lines are called the `critical curve` and `caustic`. we'll cover what these are in a later tutorial.) """ mass_profile_plottter = aplt.MassProfilePlotter(mass_profile=sis_mass_profile, grid=grid) mass_profile_plottter.figures_2d(deflections_y=True, deflections_x=True) """ __Other Properties__ `MassProfile`'s have a range of other properties that are used for lensing calculations, a couple of which we've plotted images of below: - `convergence`: The surface mass density of the mass profile in dimensionless units. - `potential`: The gravitational of the mass profile again in convenient dimensionless units. - `agnification`: Describes how much brighter each image-pixel appears due to focusing of light rays. Extracting `Array2D`'s of these quantities from **PyAutoLens** is exactly the same as for the image and deflection angles above. """ mass_profile_convergence = sis_mass_profile.convergence_2d_from(grid=grid)